blob: 3647baa9bfed302b63e6fcaf8f9726da7d050389 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
Takashi Iwai1d045db2011-07-07 18:23:21 +02004 * HD audio interface patch for Realtek ALC codecs
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Kailang Yangdf694da2005-12-05 19:42:22 +01006 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Takashi Iwai <tiwai@suse.de>
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01009 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
Paul Gortmakerda155d52011-07-15 12:38:28 -040030#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020032#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include "hda_codec.h"
34#include "hda_local.h"
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090035#include "hda_beep.h"
Takashi Iwai1835a0f2011-10-27 22:12:46 +020036#include "hda_jack.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
Takashi Iwai1d045db2011-07-07 18:23:21 +020038/* unsol event tags */
39#define ALC_FRONT_EVENT 0x01
40#define ALC_DCVOL_EVENT 0x02
41#define ALC_HP_EVENT 0x04
42#define ALC_MIC_EVENT 0x08
Takashi Iwaid4a86d82010-06-23 17:51:26 +020043
Kailang Yangdf694da2005-12-05 19:42:22 +010044/* for GPIO Poll */
45#define GPIO_MASK 0x03
46
Takashi Iwai4a79ba32009-04-22 16:31:35 +020047/* extra amp-initialization sequence types */
48enum {
49 ALC_INIT_NONE,
50 ALC_INIT_DEFAULT,
51 ALC_INIT_GPIO1,
52 ALC_INIT_GPIO2,
53 ALC_INIT_GPIO3,
54};
55
Kailang Yangda00c242010-03-19 11:23:45 +010056struct alc_customize_define {
57 unsigned int sku_cfg;
58 unsigned char port_connectivity;
59 unsigned char check_sum;
60 unsigned char customization;
61 unsigned char external_amp;
62 unsigned int enable_pcbeep:1;
63 unsigned int platform_type:1;
64 unsigned int swap:1;
65 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020066 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010067};
68
Takashi Iwaib5bfbc62011-01-13 14:22:32 +010069struct alc_fixup;
70
Takashi Iwaice764ab2011-04-27 16:35:23 +020071struct alc_multi_io {
72 hda_nid_t pin; /* multi-io widget pin NID */
73 hda_nid_t dac; /* DAC to be connected */
74 unsigned int ctl_in; /* cached input-pin control value */
75};
76
Takashi Iwaid922b512011-04-28 12:18:53 +020077enum {
Takashi Iwai3b8510c2011-04-28 14:03:24 +020078 ALC_AUTOMUTE_PIN, /* change the pin control */
79 ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
80 ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
Takashi Iwaid922b512011-04-28 12:18:53 +020081};
82
Takashi Iwaic14c95f2012-02-16 16:38:07 +010083#define MAX_VOL_NIDS 0x40
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085struct alc_spec {
86 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020087 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 unsigned int num_mixers;
Takashi Iwaia9111322011-05-02 11:30:18 +020089 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010090 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
Takashi Iwai2d9c6482009-10-13 08:06:55 +020092 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +020093 * don't forget NULL
94 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +020095 */
96 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Takashi Iwaiaa563af2009-07-31 10:05:11 +020098 char stream_name_analog[32]; /* analog PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +020099 const struct hda_pcm_stream *stream_analog_playback;
100 const struct hda_pcm_stream *stream_analog_capture;
101 const struct hda_pcm_stream *stream_analog_alt_playback;
102 const struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200104 char stream_name_digital[32]; /* digital PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +0200105 const struct hda_pcm_stream *stream_digital_playback;
106 const struct hda_pcm_stream *stream_digital_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107
108 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200109 struct hda_multi_out multiout; /* playback set-up
110 * max_channels, dacs must be set
111 * dig_out_nid and hp_nid are optional
112 */
Takashi Iwai63300792008-01-24 15:31:36 +0100113 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100114 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100115 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117 /* capture */
118 unsigned int num_adc_nids;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +0200119 const hda_nid_t *adc_nids;
120 const hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200121 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Takashi Iwai1f0f4b82011-06-27 10:52:59 +0200122 hda_nid_t mixer_nid; /* analog-mixer NID */
Takashi Iwaic14c95f2012-02-16 16:38:07 +0100123 DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1);
124 DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Takashi Iwai840b64c2010-07-13 22:49:01 +0200126 /* capture setup for dynamic dual-adc switch */
Takashi Iwai840b64c2010-07-13 22:49:01 +0200127 hda_nid_t cur_adc;
128 unsigned int cur_adc_stream_tag;
129 unsigned int cur_adc_format;
130
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200132 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 const struct hda_input_mux *input_mux;
134 unsigned int cur_mux[3];
Takashi Iwai21268962011-07-07 15:01:13 +0200135 hda_nid_t ext_mic_pin;
136 hda_nid_t dock_mic_pin;
137 hda_nid_t int_mic_pin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
139 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100140 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200142 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200143 int const_channel_count;
144 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
146 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100147 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200148
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200149 /* dynamic controls, init_verbs and input_mux */
150 struct auto_pin_cfg autocfg;
Kailang Yangda00c242010-03-19 11:23:45 +0100151 struct alc_customize_define cdefine;
Takashi Iwai603c4012008-07-30 15:01:44 +0200152 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200153 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200154 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai49535502009-06-30 15:28:30 +0200155 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
156 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai21268962011-07-07 15:01:13 +0200157 hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
158 unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
159 int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
Takashi Iwai834be882006-03-01 14:16:17 +0100160
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100161 /* hooks */
162 void (*init_hook)(struct hda_codec *codec);
163 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100164#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500165 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100166#endif
Takashi Iwai1c716152011-04-07 10:37:16 +0200167 void (*shutup)(struct hda_codec *codec);
Takashi Iwai24519912011-08-16 15:08:49 +0200168 void (*automute_hook)(struct hda_codec *codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100169
Takashi Iwai834be882006-03-01 14:16:17 +0100170 /* for pin sensing */
David Henningsson42cf0d02011-09-20 12:04:56 +0200171 unsigned int hp_jack_present:1;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200172 unsigned int line_jack_present:1;
Takashi Iwaie9427962011-04-28 15:46:07 +0200173 unsigned int master_mute:1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200174 unsigned int auto_mic:1;
Takashi Iwai21268962011-07-07 15:01:13 +0200175 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
David Henningsson42cf0d02011-09-20 12:04:56 +0200176 unsigned int automute_speaker:1; /* automute speaker outputs */
177 unsigned int automute_lo:1; /* automute LO outputs */
178 unsigned int detect_hp:1; /* Headphone detection enabled */
179 unsigned int detect_lo:1; /* Line-out detection enabled */
180 unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
181 unsigned int automute_lo_possible:1; /* there are line outs and HP */
Takashi Iwai31150f22012-01-30 10:54:08 +0100182 unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
Takashi Iwaicb53c622007-08-10 17:21:45 +0200183
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100184 /* other flags */
185 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai21268962011-07-07 15:01:13 +0200186 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai584c0c42011-03-10 12:51:11 +0100187 unsigned int single_input_src:1;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +0200188 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
Takashi Iwai53c334a2011-08-23 18:27:14 +0200189 unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
Takashi Iwai24de1832011-11-07 17:13:39 +0100190 unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
Takashi Iwaid922b512011-04-28 12:18:53 +0200191
192 /* auto-mute control */
193 int automute_mode;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200194 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
Takashi Iwaid922b512011-04-28 12:18:53 +0200195
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200196 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200197 int codec_variant; /* flag for other variants */
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100198
Takashi Iwai2134ea42008-01-10 16:53:55 +0100199 /* for virtual master */
200 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200201#ifdef CONFIG_SND_HDA_POWER_SAVE
202 struct hda_loopback_check loopback;
203#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200204
205 /* for PLL fix */
206 hda_nid_t pll_nid;
207 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwai1bb7e432011-10-17 16:50:59 +0200208 unsigned int coef0;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +0100209
210 /* fix-up list */
211 int fixup_id;
212 const struct alc_fixup *fixup_list;
213 const char *fixup_name;
Takashi Iwaice764ab2011-04-27 16:35:23 +0200214
215 /* multi-io */
216 int multi_ios;
217 struct alc_multi_io multi_io[4];
Takashi Iwai23c09b02011-08-19 09:05:35 +0200218
219 /* bind volumes */
220 struct snd_array bind_ctls;
Kailang Yangdf694da2005-12-05 19:42:22 +0100221};
222
Takashi Iwai1d045db2011-07-07 18:23:21 +0200223#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
Takashi Iwai44c02402011-07-08 15:14:19 +0200225static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
226 int dir, unsigned int bits)
227{
228 if (!nid)
229 return false;
230 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
231 if (query_amp_caps(codec, nid, dir) & bits)
232 return true;
233 return false;
234}
235
236#define nid_has_mute(codec, nid, dir) \
237 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
238#define nid_has_volume(codec, nid, dir) \
239 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241/*
242 * input MUX handling
243 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200244static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
245 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246{
247 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
248 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200249 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
250 if (mux_idx >= spec->num_mux_defs)
251 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100252 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
253 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200254 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255}
256
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200257static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
258 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259{
260 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
261 struct alc_spec *spec = codec->spec;
262 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
263
264 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
265 return 0;
266}
267
Takashi Iwai21268962011-07-07 15:01:13 +0200268static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
Takashi Iwai21268962011-07-07 15:01:13 +0200270 struct alc_spec *spec = codec->spec;
271 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
272
273 if (spec->cur_adc && spec->cur_adc != new_adc) {
274 /* stream is running, let's swap the current ADC */
275 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
276 spec->cur_adc = new_adc;
277 snd_hda_codec_setup_stream(codec, new_adc,
278 spec->cur_adc_stream_tag, 0,
279 spec->cur_adc_format);
280 return true;
281 }
282 return false;
283}
284
Takashi Iwai61071592011-11-23 07:52:15 +0100285static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx)
286{
287 return spec->capsrc_nids ?
288 spec->capsrc_nids[idx] : spec->adc_nids[idx];
289}
290
Takashi Iwai24de1832011-11-07 17:13:39 +0100291static void call_update_outputs(struct hda_codec *codec);
292
Takashi Iwai21268962011-07-07 15:01:13 +0200293/* select the given imux item; either unmute exclusively or select the route */
294static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
295 unsigned int idx, bool force)
296{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100298 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100299 unsigned int mux_idx;
Takashi Iwaidccc1812011-11-08 07:52:19 +0100300 int i, type, num_conns;
Takashi Iwai21268962011-07-07 15:01:13 +0200301 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Takashi Iwaicd896c32008-11-18 12:36:33 +0100303 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
304 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100305 if (!imux->num_items && mux_idx > 0)
306 imux = &spec->input_mux[0];
Takashi Iwaicce4aa32011-12-02 15:29:12 +0100307 if (!imux->num_items)
308 return 0;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100309
Takashi Iwai21268962011-07-07 15:01:13 +0200310 if (idx >= imux->num_items)
311 idx = imux->num_items - 1;
312 if (spec->cur_mux[adc_idx] == idx && !force)
313 return 0;
314 spec->cur_mux[adc_idx] = idx;
315
Takashi Iwai24de1832011-11-07 17:13:39 +0100316 /* for shared I/O, change the pin-control accordingly */
317 if (spec->shared_mic_hp) {
318 /* NOTE: this assumes that there are only two inputs, the
319 * first is the real internal mic and the second is HP jack.
320 */
321 snd_hda_codec_write(codec, spec->autocfg.inputs[1].pin, 0,
322 AC_VERB_SET_PIN_WIDGET_CONTROL,
323 spec->cur_mux[adc_idx] ?
324 PIN_VREF80 : PIN_HP);
325 spec->automute_speaker = !spec->cur_mux[adc_idx];
326 call_update_outputs(codec);
327 }
328
Takashi Iwai21268962011-07-07 15:01:13 +0200329 if (spec->dyn_adc_switch) {
330 alc_dyn_adc_pcm_resetup(codec, idx);
331 adc_idx = spec->dyn_adc_idx[idx];
332 }
333
Takashi Iwai61071592011-11-23 07:52:15 +0100334 nid = get_capsrc(spec, adc_idx);
Takashi Iwai21268962011-07-07 15:01:13 +0200335
336 /* no selection? */
Takashi Iwaidccc1812011-11-08 07:52:19 +0100337 num_conns = snd_hda_get_conn_list(codec, nid, NULL);
338 if (num_conns <= 1)
Takashi Iwai21268962011-07-07 15:01:13 +0200339 return 1;
340
Takashi Iwaia22d5432009-07-27 12:54:26 +0200341 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200342 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100343 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwaidccc1812011-11-08 07:52:19 +0100344 int active = imux->items[idx].index;
345 for (i = 0; i < num_conns; i++) {
346 unsigned int v = (i == active) ? 0 : HDA_AMP_MUTE;
347 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, i,
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100348 HDA_AMP_MUTE, v);
349 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100350 } else {
351 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200352 snd_hda_codec_write_cache(codec, nid, 0,
353 AC_VERB_SET_CONNECT_SEL,
354 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100355 }
Takashi Iwai21268962011-07-07 15:01:13 +0200356 return 1;
357}
358
359static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
360 struct snd_ctl_elem_value *ucontrol)
361{
362 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
363 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
364 return alc_mux_select(codec, adc_idx,
365 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100366}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200367
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100369 * set up the input pin config (depending on the given auto-pin type)
370 */
371static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
372 int auto_pin_type)
373{
374 unsigned int val = PIN_IN;
375
Takashi Iwai86e29592010-09-09 14:50:17 +0200376 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100377 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200378 unsigned int oldval;
379 oldval = snd_hda_codec_read(codec, nid, 0,
380 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100381 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100382 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200383 /* if the default pin setup is vref50, we give it priority */
384 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100385 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200386 else if (pincap & AC_PINCAP_VREF_50)
387 val = PIN_VREF50;
388 else if (pincap & AC_PINCAP_VREF_100)
389 val = PIN_VREF100;
390 else if (pincap & AC_PINCAP_VREF_GRD)
391 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100392 }
393 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
394}
395
396/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200397 * Append the given mixer and verb elements for the later use
398 * The mixer array is referred in build_controls(), and init_verbs are
399 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100400 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200401static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100402{
403 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
404 return;
405 spec->mixers[spec->num_mixers++] = mix;
406}
407
408static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
409{
410 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
411 return;
412 spec->init_verbs[spec->num_init_verbs++] = verb;
413}
414
415/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200416 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100417 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200418/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200419static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200420 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
421 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
422 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
423 { }
424};
425
Takashi Iwaia9111322011-05-02 11:30:18 +0200426static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200427 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
428 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
429 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
430 { }
431};
432
Takashi Iwaia9111322011-05-02 11:30:18 +0200433static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200434 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
435 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
436 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
437 { }
438};
439
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200440/*
441 * Fix hardware PLL issue
442 * On some codecs, the analog PLL gating control must be off while
443 * the default value is 1.
444 */
445static void alc_fix_pll(struct hda_codec *codec)
446{
447 struct alc_spec *spec = codec->spec;
448 unsigned int val;
449
450 if (!spec->pll_nid)
451 return;
452 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
453 spec->pll_coef_idx);
454 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
455 AC_VERB_GET_PROC_COEF, 0);
456 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
457 spec->pll_coef_idx);
458 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
459 val & ~(1 << spec->pll_coef_bit));
460}
461
462static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
463 unsigned int coef_idx, unsigned int coef_bit)
464{
465 struct alc_spec *spec = codec->spec;
466 spec->pll_nid = nid;
467 spec->pll_coef_idx = coef_idx;
468 spec->pll_coef_bit = coef_bit;
469 alc_fix_pll(codec);
470}
471
Takashi Iwai1d045db2011-07-07 18:23:21 +0200472/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200473 * Jack detections for HP auto-mute and mic-switch
474 */
475
476/* check each pin in the given array; returns true if any of them is plugged */
477static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200478{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200479 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200480
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200481 for (i = 0; i < num_pins; i++) {
482 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200483 if (!nid)
484 break;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200485 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200486 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200487 return present;
488}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200489
Takashi Iwai1d045db2011-07-07 18:23:21 +0200490/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200491static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200492 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200493{
494 struct alc_spec *spec = codec->spec;
495 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200496 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200497 int i;
498
499 for (i = 0; i < num_pins; i++) {
500 hda_nid_t nid = pins[i];
Takashi Iwai31150f22012-01-30 10:54:08 +0100501 unsigned int val;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200502 if (!nid)
503 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200504 switch (spec->automute_mode) {
505 case ALC_AUTOMUTE_PIN:
Takashi Iwai31150f22012-01-30 10:54:08 +0100506 /* don't reset VREF value in case it's controlling
507 * the amp (see alc861_fixup_asus_amp_vref_0f())
508 */
509 if (spec->keep_vref_in_automute) {
510 val = snd_hda_codec_read(codec, nid, 0,
511 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
512 val &= ~PIN_HP;
513 } else
514 val = 0;
515 val |= pin_bits;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200516 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200517 AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwai31150f22012-01-30 10:54:08 +0100518 val);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200519 break;
520 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200521 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200522 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200523 break;
524 case ALC_AUTOMUTE_MIXER:
525 nid = spec->automute_mixer_nid[i];
526 if (!nid)
527 break;
528 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200529 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200530 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200531 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200532 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200533 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200534 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200535}
536
David Henningsson42cf0d02011-09-20 12:04:56 +0200537/* Toggle outputs muting */
538static void update_outputs(struct hda_codec *codec)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200539{
540 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200541 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200542
Takashi Iwaic0a20262011-06-10 15:28:15 +0200543 /* Control HP pins/amps depending on master_mute state;
544 * in general, HP pins/amps control should be enabled in all cases,
545 * but currently set only for master_mute, just to be safe
546 */
Takashi Iwai24de1832011-11-07 17:13:39 +0100547 if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
548 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
Takashi Iwaic0a20262011-06-10 15:28:15 +0200549 spec->autocfg.hp_pins, spec->master_mute, true);
550
David Henningsson42cf0d02011-09-20 12:04:56 +0200551 if (!spec->automute_speaker)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200552 on = 0;
553 else
David Henningsson42cf0d02011-09-20 12:04:56 +0200554 on = spec->hp_jack_present | spec->line_jack_present;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200555 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200556 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200557 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200558
559 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200560 /* if LO is a copy of either HP or Speaker, don't need to handle it */
561 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
562 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200563 return;
David Henningsson42cf0d02011-09-20 12:04:56 +0200564 if (!spec->automute_lo)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200565 on = 0;
566 else
David Henningsson42cf0d02011-09-20 12:04:56 +0200567 on = spec->hp_jack_present;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200568 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200569 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200570 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200571}
572
David Henningsson42cf0d02011-09-20 12:04:56 +0200573static void call_update_outputs(struct hda_codec *codec)
Takashi Iwai24519912011-08-16 15:08:49 +0200574{
575 struct alc_spec *spec = codec->spec;
576 if (spec->automute_hook)
577 spec->automute_hook(codec);
578 else
David Henningsson42cf0d02011-09-20 12:04:56 +0200579 update_outputs(codec);
Takashi Iwai24519912011-08-16 15:08:49 +0200580}
581
Takashi Iwai1d045db2011-07-07 18:23:21 +0200582/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200583static void alc_hp_automute(struct hda_codec *codec)
584{
585 struct alc_spec *spec = codec->spec;
586
David Henningsson42cf0d02011-09-20 12:04:56 +0200587 spec->hp_jack_present =
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200588 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
589 spec->autocfg.hp_pins);
David Henningsson42cf0d02011-09-20 12:04:56 +0200590 if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
Takashi Iwai3c715a92011-08-23 12:41:09 +0200591 return;
David Henningsson42cf0d02011-09-20 12:04:56 +0200592 call_update_outputs(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200593}
594
Takashi Iwai1d045db2011-07-07 18:23:21 +0200595/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200596static void alc_line_automute(struct hda_codec *codec)
597{
598 struct alc_spec *spec = codec->spec;
599
Takashi Iwaie0d32e32011-09-26 15:19:55 +0200600 /* check LO jack only when it's different from HP */
601 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
602 return;
603
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200604 spec->line_jack_present =
605 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
606 spec->autocfg.line_out_pins);
David Henningsson42cf0d02011-09-20 12:04:56 +0200607 if (!spec->automute_speaker || !spec->detect_lo)
Takashi Iwai3c715a92011-08-23 12:41:09 +0200608 return;
David Henningsson42cf0d02011-09-20 12:04:56 +0200609 call_update_outputs(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200610}
611
Takashi Iwai8d087c72011-06-28 12:45:47 +0200612#define get_connection_index(codec, mux, nid) \
613 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200614
Takashi Iwai1d045db2011-07-07 18:23:21 +0200615/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200616static void alc_mic_automute(struct hda_codec *codec)
617{
618 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200619 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200620
Takashi Iwai21268962011-07-07 15:01:13 +0200621 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200622 return;
623 if (snd_BUG_ON(!spec->adc_nids))
624 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200625 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200626 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200627
Takashi Iwai21268962011-07-07 15:01:13 +0200628 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
629 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
630 else if (spec->dock_mic_idx >= 0 &&
631 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
632 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
633 else
634 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200635}
636
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100637/* handle the specified unsol action (ALC_XXX_EVENT) */
638static void alc_exec_unsol_event(struct hda_codec *codec, int action)
Kailang Yangc9b58002007-10-16 14:30:01 +0200639{
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100640 switch (action) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200641 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200642 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200643 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200644 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200645 alc_line_automute(codec);
646 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200647 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200648 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200649 break;
650 }
Takashi Iwai01a61e12011-10-28 00:03:22 +0200651 snd_hda_jack_report_sync(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200652}
653
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100654/* unsolicited event for HP jack sensing */
655static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
656{
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100657 if (codec->vendor_id == 0x10ec0880)
658 res >>= 28;
659 else
660 res >>= 26;
Takashi Iwaia7309792012-01-19 15:03:48 +0100661 res = snd_hda_jack_get_action(codec, res);
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100662 alc_exec_unsol_event(codec, res);
663}
664
Takashi Iwai1d045db2011-07-07 18:23:21 +0200665/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200666static void alc_inithook(struct hda_codec *codec)
667{
Takashi Iwaid922b512011-04-28 12:18:53 +0200668 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200669 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200670 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200671}
672
Kailang Yangf9423e72008-05-27 12:32:25 +0200673/* additional initialization for ALC888 variants */
674static void alc888_coef_init(struct hda_codec *codec)
675{
676 unsigned int tmp;
677
678 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
679 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
680 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100681 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200682 /* alc888S-VC */
683 snd_hda_codec_read(codec, 0x20, 0,
684 AC_VERB_SET_PROC_COEF, 0x830);
685 else
686 /* alc888-VB */
687 snd_hda_codec_read(codec, 0x20, 0,
688 AC_VERB_SET_PROC_COEF, 0x3030);
689}
690
Takashi Iwai1d045db2011-07-07 18:23:21 +0200691/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200692static void alc889_coef_init(struct hda_codec *codec)
693{
694 unsigned int tmp;
695
696 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
697 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
698 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
699 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
700}
701
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100702/* turn on/off EAPD control (only if available) */
703static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
704{
705 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
706 return;
707 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
708 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
709 on ? 2 : 0);
710}
711
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200712/* turn on/off EAPD controls of the codec */
713static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
714{
715 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200716 static hda_nid_t pins[] = {
717 0x0f, 0x10, 0x14, 0x15, 0
718 };
719 hda_nid_t *p;
720 for (p = pins; *p; p++)
721 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200722}
723
Takashi Iwai1c716152011-04-07 10:37:16 +0200724/* generic shutup callback;
725 * just turning off EPAD and a little pause for avoiding pop-noise
726 */
727static void alc_eapd_shutup(struct hda_codec *codec)
728{
729 alc_auto_setup_eapd(codec, false);
730 msleep(200);
731}
732
Takashi Iwai1d045db2011-07-07 18:23:21 +0200733/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200734static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200735{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200736 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200737
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200738 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200739 switch (type) {
740 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200741 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
742 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200743 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200744 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
745 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200746 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200747 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
748 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200749 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200750 switch (codec->vendor_id) {
751 case 0x10ec0260:
752 snd_hda_codec_write(codec, 0x1a, 0,
753 AC_VERB_SET_COEF_INDEX, 7);
754 tmp = snd_hda_codec_read(codec, 0x1a, 0,
755 AC_VERB_GET_PROC_COEF, 0);
756 snd_hda_codec_write(codec, 0x1a, 0,
757 AC_VERB_SET_COEF_INDEX, 7);
758 snd_hda_codec_write(codec, 0x1a, 0,
759 AC_VERB_SET_PROC_COEF,
760 tmp | 0x2010);
761 break;
762 case 0x10ec0262:
763 case 0x10ec0880:
764 case 0x10ec0882:
765 case 0x10ec0883:
766 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100767 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100768 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200769 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200770 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200771 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200772 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200773 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100774#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200775 case 0x10ec0267:
776 case 0x10ec0268:
777 snd_hda_codec_write(codec, 0x20, 0,
778 AC_VERB_SET_COEF_INDEX, 7);
779 tmp = snd_hda_codec_read(codec, 0x20, 0,
780 AC_VERB_GET_PROC_COEF, 0);
781 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200782 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200783 snd_hda_codec_write(codec, 0x20, 0,
784 AC_VERB_SET_PROC_COEF,
785 tmp | 0x3000);
786 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100787#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200788 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200789 break;
790 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200791}
Kailang Yangea1fb292008-08-26 12:58:38 +0200792
Takashi Iwai1d045db2011-07-07 18:23:21 +0200793/*
794 * Auto-Mute mode mixer enum support
795 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200796static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
797 struct snd_ctl_elem_info *uinfo)
798{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200799 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
800 struct alc_spec *spec = codec->spec;
801 static const char * const texts2[] = {
802 "Disabled", "Enabled"
803 };
804 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200805 "Disabled", "Speaker Only", "Line-Out+Speaker"
806 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200807 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200808
809 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
810 uinfo->count = 1;
David Henningsson42cf0d02011-09-20 12:04:56 +0200811 if (spec->automute_speaker_possible && spec->automute_lo_possible) {
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200812 uinfo->value.enumerated.items = 3;
813 texts = texts3;
814 } else {
815 uinfo->value.enumerated.items = 2;
816 texts = texts2;
817 }
818 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
819 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200820 strcpy(uinfo->value.enumerated.name,
821 texts[uinfo->value.enumerated.item]);
822 return 0;
823}
824
825static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
826 struct snd_ctl_elem_value *ucontrol)
827{
828 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
829 struct alc_spec *spec = codec->spec;
David Henningsson42cf0d02011-09-20 12:04:56 +0200830 unsigned int val = 0;
831 if (spec->automute_speaker)
832 val++;
833 if (spec->automute_lo)
834 val++;
835
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200836 ucontrol->value.enumerated.item[0] = val;
837 return 0;
838}
839
840static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
841 struct snd_ctl_elem_value *ucontrol)
842{
843 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
844 struct alc_spec *spec = codec->spec;
845
846 switch (ucontrol->value.enumerated.item[0]) {
847 case 0:
David Henningsson42cf0d02011-09-20 12:04:56 +0200848 if (!spec->automute_speaker && !spec->automute_lo)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200849 return 0;
David Henningsson42cf0d02011-09-20 12:04:56 +0200850 spec->automute_speaker = 0;
851 spec->automute_lo = 0;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200852 break;
853 case 1:
David Henningsson42cf0d02011-09-20 12:04:56 +0200854 if (spec->automute_speaker_possible) {
855 if (!spec->automute_lo && spec->automute_speaker)
856 return 0;
857 spec->automute_speaker = 1;
858 spec->automute_lo = 0;
859 } else if (spec->automute_lo_possible) {
860 if (spec->automute_lo)
861 return 0;
862 spec->automute_lo = 1;
863 } else
864 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200865 break;
866 case 2:
David Henningsson42cf0d02011-09-20 12:04:56 +0200867 if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200868 return -EINVAL;
David Henningsson42cf0d02011-09-20 12:04:56 +0200869 if (spec->automute_speaker && spec->automute_lo)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200870 return 0;
David Henningsson42cf0d02011-09-20 12:04:56 +0200871 spec->automute_speaker = 1;
872 spec->automute_lo = 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200873 break;
874 default:
875 return -EINVAL;
876 }
David Henningsson42cf0d02011-09-20 12:04:56 +0200877 call_update_outputs(codec);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200878 return 1;
879}
880
Takashi Iwaia9111322011-05-02 11:30:18 +0200881static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200882 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
883 .name = "Auto-Mute Mode",
884 .info = alc_automute_mode_info,
885 .get = alc_automute_mode_get,
886 .put = alc_automute_mode_put,
887};
888
Takashi Iwai1d045db2011-07-07 18:23:21 +0200889static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
890{
891 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
892 return snd_array_new(&spec->kctls);
893}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200894
895static int alc_add_automute_mode_enum(struct hda_codec *codec)
896{
897 struct alc_spec *spec = codec->spec;
898 struct snd_kcontrol_new *knew;
899
900 knew = alc_kcontrol_new(spec);
901 if (!knew)
902 return -ENOMEM;
903 *knew = alc_automute_mode_enum;
904 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
905 if (!knew->name)
906 return -ENOMEM;
907 return 0;
908}
909
Takashi Iwai1d045db2011-07-07 18:23:21 +0200910/*
911 * Check the availability of HP/line-out auto-mute;
912 * Set up appropriately if really supported
913 */
David Henningsson42cf0d02011-09-20 12:04:56 +0200914static void alc_init_automute(struct hda_codec *codec)
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200915{
916 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200917 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200918 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200919 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200920
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200921 if (cfg->hp_pins[0])
922 present++;
923 if (cfg->line_out_pins[0])
924 present++;
925 if (cfg->speaker_pins[0])
926 present++;
927 if (present < 2) /* need two different output types */
928 return;
Kailang Yangc9b58002007-10-16 14:30:01 +0200929
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200930 if (!cfg->speaker_pins[0] &&
931 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200932 memcpy(cfg->speaker_pins, cfg->line_out_pins,
933 sizeof(cfg->speaker_pins));
934 cfg->speaker_outs = cfg->line_outs;
935 }
936
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200937 if (!cfg->hp_pins[0] &&
938 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200939 memcpy(cfg->hp_pins, cfg->line_out_pins,
940 sizeof(cfg->hp_pins));
941 cfg->hp_outs = cfg->line_outs;
942 }
943
David Henningsson42cf0d02011-09-20 12:04:56 +0200944 spec->automute_mode = ALC_AUTOMUTE_PIN;
945
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200946 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200947 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200948 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200949 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200950 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200951 nid);
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200952 snd_hda_jack_detect_enable(codec, nid, ALC_HP_EVENT);
David Henningsson42cf0d02011-09-20 12:04:56 +0200953 spec->detect_hp = 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200954 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200955
David Henningsson42cf0d02011-09-20 12:04:56 +0200956 if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
957 if (cfg->speaker_outs)
958 for (i = 0; i < cfg->line_outs; i++) {
959 hda_nid_t nid = cfg->line_out_pins[i];
960 if (!is_jack_detectable(codec, nid))
961 continue;
962 snd_printdd("realtek: Enable Line-Out "
963 "auto-muting on NID 0x%x\n", nid);
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200964 snd_hda_jack_detect_enable(codec, nid,
965 ALC_FRONT_EVENT);
David Henningsson42cf0d02011-09-20 12:04:56 +0200966 spec->detect_lo = 1;
967 }
968 spec->automute_lo_possible = spec->detect_hp;
969 }
970
971 spec->automute_speaker_possible = cfg->speaker_outs &&
972 (spec->detect_hp || spec->detect_lo);
973
974 spec->automute_lo = spec->automute_lo_possible;
975 spec->automute_speaker = spec->automute_speaker_possible;
976
977 if (spec->automute_speaker_possible || spec->automute_lo_possible) {
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200978 /* create a control for automute mode */
979 alc_add_automute_mode_enum(codec);
980 spec->unsol_event = alc_sku_unsol_event;
981 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200982}
983
Takashi Iwai1d045db2011-07-07 18:23:21 +0200984/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200985static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
986{
987 int i;
988 for (i = 0; i < nums; i++)
989 if (list[i] == nid)
990 return i;
991 return -1;
992}
993
Takashi Iwai1d045db2011-07-07 18:23:21 +0200994/* check whether dynamic ADC-switching is available */
995static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
996{
997 struct alc_spec *spec = codec->spec;
998 struct hda_input_mux *imux = &spec->private_imux[0];
999 int i, n, idx;
1000 hda_nid_t cap, pin;
1001
1002 if (imux != spec->input_mux) /* no dynamic imux? */
1003 return false;
1004
1005 for (n = 0; n < spec->num_adc_nids; n++) {
1006 cap = spec->private_capsrc_nids[n];
1007 for (i = 0; i < imux->num_items; i++) {
1008 pin = spec->imux_pins[i];
1009 if (!pin)
1010 return false;
1011 if (get_connection_index(codec, cap, pin) < 0)
1012 break;
1013 }
1014 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +02001015 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001016 }
1017
1018 for (i = 0; i < imux->num_items; i++) {
1019 pin = spec->imux_pins[i];
1020 for (n = 0; n < spec->num_adc_nids; n++) {
1021 cap = spec->private_capsrc_nids[n];
1022 idx = get_connection_index(codec, cap, pin);
1023 if (idx >= 0) {
1024 imux->items[i].index = idx;
1025 spec->dyn_adc_idx[i] = n;
1026 break;
1027 }
1028 }
1029 }
1030
1031 snd_printdd("realtek: enabling ADC switching\n");
1032 spec->dyn_adc_switch = 1;
1033 return true;
1034}
Takashi Iwai21268962011-07-07 15:01:13 +02001035
1036/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1037static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1038{
1039 struct alc_spec *spec = codec->spec;
1040 struct hda_input_mux *imux;
1041 static char * const texts[3] = {
1042 "Mic", "Internal Mic", "Dock Mic"
1043 };
1044 int i;
1045
1046 if (!spec->auto_mic)
1047 return false;
1048 imux = &spec->private_imux[0];
1049 if (spec->input_mux == imux)
1050 return true;
1051 spec->imux_pins[0] = spec->ext_mic_pin;
1052 spec->imux_pins[1] = spec->int_mic_pin;
1053 spec->imux_pins[2] = spec->dock_mic_pin;
1054 for (i = 0; i < 3; i++) {
1055 strcpy(imux->items[i].label, texts[i]);
Takashi Iwai6759dc32011-11-23 07:38:59 +01001056 if (spec->imux_pins[i]) {
1057 hda_nid_t pin = spec->imux_pins[i];
1058 int c;
1059 for (c = 0; c < spec->num_adc_nids; c++) {
Takashi Iwai61071592011-11-23 07:52:15 +01001060 hda_nid_t cap = get_capsrc(spec, c);
Takashi Iwai6759dc32011-11-23 07:38:59 +01001061 int idx = get_connection_index(codec, cap, pin);
1062 if (idx >= 0) {
1063 imux->items[i].index = idx;
1064 break;
1065 }
1066 }
Takashi Iwai21268962011-07-07 15:01:13 +02001067 imux->num_items = i + 1;
Takashi Iwai6759dc32011-11-23 07:38:59 +01001068 }
Takashi Iwai21268962011-07-07 15:01:13 +02001069 }
1070 spec->num_mux_defs = 1;
1071 spec->input_mux = imux;
1072 return true;
1073}
1074
1075/* check whether all auto-mic pins are valid; setup indices if OK */
1076static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1077{
1078 struct alc_spec *spec = codec->spec;
1079 const struct hda_input_mux *imux;
1080
1081 if (!spec->auto_mic)
1082 return false;
1083 if (spec->auto_mic_valid_imux)
1084 return true; /* already checked */
1085
1086 /* fill up imux indices */
1087 if (!alc_check_dyn_adc_switch(codec)) {
1088 spec->auto_mic = 0;
1089 return false;
1090 }
1091
1092 imux = spec->input_mux;
1093 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1094 spec->imux_pins, imux->num_items);
1095 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1096 spec->imux_pins, imux->num_items);
1097 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1098 spec->imux_pins, imux->num_items);
1099 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1100 spec->auto_mic = 0;
1101 return false; /* no corresponding imux */
1102 }
1103
Takashi Iwai1835a0f2011-10-27 22:12:46 +02001104 snd_hda_jack_detect_enable(codec, spec->ext_mic_pin, ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001105 if (spec->dock_mic_pin)
Takashi Iwai1835a0f2011-10-27 22:12:46 +02001106 snd_hda_jack_detect_enable(codec, spec->dock_mic_pin,
1107 ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001108
1109 spec->auto_mic_valid_imux = 1;
1110 spec->auto_mic = 1;
1111 return true;
1112}
1113
Takashi Iwai1d045db2011-07-07 18:23:21 +02001114/*
1115 * Check the availability of auto-mic switch;
1116 * Set up if really supported
1117 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001118static void alc_init_auto_mic(struct hda_codec *codec)
1119{
1120 struct alc_spec *spec = codec->spec;
1121 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001122 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001123 int i;
1124
Takashi Iwai24de1832011-11-07 17:13:39 +01001125 if (spec->shared_mic_hp)
1126 return; /* no auto-mic for the shared I/O */
1127
Takashi Iwai21268962011-07-07 15:01:13 +02001128 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1129
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001130 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001131 for (i = 0; i < cfg->num_inputs; i++) {
1132 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001133 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001134 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001135 switch (snd_hda_get_input_pin_attr(defcfg)) {
1136 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001137 if (fixed)
1138 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001139 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1140 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001141 fixed = nid;
1142 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001143 case INPUT_PIN_ATTR_UNUSED:
1144 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001145 case INPUT_PIN_ATTR_DOCK:
1146 if (dock)
1147 return; /* already occupied */
1148 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1149 return; /* invalid type */
1150 dock = nid;
1151 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001152 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001153 if (ext)
1154 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001155 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1156 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001157 ext = nid;
1158 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001159 }
1160 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001161 if (!ext && dock) {
1162 ext = dock;
1163 dock = 0;
1164 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001165 if (!ext || !fixed)
1166 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001167 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001168 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001169 if (dock && !is_jack_detectable(codec, dock))
1170 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001171
1172 /* check imux indices */
1173 spec->ext_mic_pin = ext;
1174 spec->int_mic_pin = fixed;
1175 spec->dock_mic_pin = dock;
1176
1177 spec->auto_mic = 1;
1178 if (!alc_auto_mic_check_imux(codec))
1179 return;
1180
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001181 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1182 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001183 spec->unsol_event = alc_sku_unsol_event;
1184}
1185
Takashi Iwai1d045db2011-07-07 18:23:21 +02001186/* check the availabilities of auto-mute and auto-mic switches */
1187static void alc_auto_check_switches(struct hda_codec *codec)
1188{
David Henningsson42cf0d02011-09-20 12:04:56 +02001189 alc_init_automute(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001190 alc_init_auto_mic(codec);
1191}
1192
1193/*
1194 * Realtek SSID verification
1195 */
1196
David Henningsson90622912010-10-14 14:50:18 +02001197/* Could be any non-zero and even value. When used as fixup, tells
1198 * the driver to ignore any present sku defines.
1199 */
1200#define ALC_FIXUP_SKU_IGNORE (2)
1201
Kailang Yangda00c242010-03-19 11:23:45 +01001202static int alc_auto_parse_customize_define(struct hda_codec *codec)
1203{
1204 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001205 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001206 struct alc_spec *spec = codec->spec;
1207
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001208 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1209
David Henningsson90622912010-10-14 14:50:18 +02001210 if (spec->cdefine.fixup) {
1211 ass = spec->cdefine.sku_cfg;
1212 if (ass == ALC_FIXUP_SKU_IGNORE)
1213 return -1;
1214 goto do_sku;
1215 }
1216
Kailang Yangda00c242010-03-19 11:23:45 +01001217 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001218 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001219 goto do_sku;
1220
1221 nid = 0x1d;
1222 if (codec->vendor_id == 0x10ec0260)
1223 nid = 0x17;
1224 ass = snd_hda_codec_get_pincfg(codec, nid);
1225
1226 if (!(ass & 1)) {
1227 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1228 codec->chip_name, ass);
1229 return -1;
1230 }
1231
1232 /* check sum */
1233 tmp = 0;
1234 for (i = 1; i < 16; i++) {
1235 if ((ass >> i) & 1)
1236 tmp++;
1237 }
1238 if (((ass >> 16) & 0xf) != tmp)
1239 return -1;
1240
1241 spec->cdefine.port_connectivity = ass >> 30;
1242 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1243 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1244 spec->cdefine.customization = ass >> 8;
1245do_sku:
1246 spec->cdefine.sku_cfg = ass;
1247 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1248 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1249 spec->cdefine.swap = (ass & 0x2) >> 1;
1250 spec->cdefine.override = ass & 0x1;
1251
1252 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1253 nid, spec->cdefine.sku_cfg);
1254 snd_printd("SKU: port_connectivity=0x%x\n",
1255 spec->cdefine.port_connectivity);
1256 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1257 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1258 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1259 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1260 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1261 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1262 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1263
1264 return 0;
1265}
1266
Takashi Iwai1d045db2011-07-07 18:23:21 +02001267/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001268static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1269{
Takashi Iwai21268962011-07-07 15:01:13 +02001270 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001271}
1272
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001273/* check subsystem ID and set up device-specific initialization;
1274 * return 1 if initialized, 0 if invalid SSID
1275 */
1276/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1277 * 31 ~ 16 : Manufacture ID
1278 * 15 ~ 8 : SKU ID
1279 * 7 ~ 0 : Assembly ID
1280 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1281 */
1282static int alc_subsystem_id(struct hda_codec *codec,
1283 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001284 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001285{
1286 unsigned int ass, tmp, i;
1287 unsigned nid;
1288 struct alc_spec *spec = codec->spec;
1289
David Henningsson90622912010-10-14 14:50:18 +02001290 if (spec->cdefine.fixup) {
1291 ass = spec->cdefine.sku_cfg;
1292 if (ass == ALC_FIXUP_SKU_IGNORE)
1293 return 0;
1294 goto do_sku;
1295 }
1296
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001297 ass = codec->subsystem_id & 0xffff;
1298 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1299 goto do_sku;
1300
1301 /* invalid SSID, check the special NID pin defcfg instead */
1302 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001303 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001304 * 29~21 : reserve
1305 * 20 : PCBEEP input
1306 * 19~16 : Check sum (15:1)
1307 * 15~1 : Custom
1308 * 0 : override
1309 */
1310 nid = 0x1d;
1311 if (codec->vendor_id == 0x10ec0260)
1312 nid = 0x17;
1313 ass = snd_hda_codec_get_pincfg(codec, nid);
1314 snd_printd("realtek: No valid SSID, "
1315 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001316 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001317 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001318 return 0;
1319 if ((ass >> 30) != 1) /* no physical connection */
1320 return 0;
1321
1322 /* check sum */
1323 tmp = 0;
1324 for (i = 1; i < 16; i++) {
1325 if ((ass >> i) & 1)
1326 tmp++;
1327 }
1328 if (((ass >> 16) & 0xf) != tmp)
1329 return 0;
1330do_sku:
1331 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1332 ass & 0xffff, codec->vendor_id);
1333 /*
1334 * 0 : override
1335 * 1 : Swap Jack
1336 * 2 : 0 --> Desktop, 1 --> Laptop
1337 * 3~5 : External Amplifier control
1338 * 7~6 : Reserved
1339 */
1340 tmp = (ass & 0x38) >> 3; /* external Amp control */
1341 switch (tmp) {
1342 case 1:
1343 spec->init_amp = ALC_INIT_GPIO1;
1344 break;
1345 case 3:
1346 spec->init_amp = ALC_INIT_GPIO2;
1347 break;
1348 case 7:
1349 spec->init_amp = ALC_INIT_GPIO3;
1350 break;
1351 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001352 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001353 spec->init_amp = ALC_INIT_DEFAULT;
1354 break;
1355 }
1356
1357 /* is laptop or Desktop and enable the function "Mute internal speaker
1358 * when the external headphone out jack is plugged"
1359 */
1360 if (!(ass & 0x8000))
1361 return 1;
1362 /*
1363 * 10~8 : Jack location
1364 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1365 * 14~13: Resvered
1366 * 15 : 1 --> enable the function "Mute internal speaker
1367 * when the external headphone out jack is plugged"
1368 */
Takashi Iwai5fe6e012011-09-26 10:41:21 +02001369 if (!spec->autocfg.hp_pins[0] &&
1370 !(spec->autocfg.line_out_pins[0] &&
1371 spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001372 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001373 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1374 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001375 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001376 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001377 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001378 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001379 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001380 else if (tmp == 3)
1381 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001382 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001383 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001384 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1385 spec->autocfg.line_outs))
1386 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001387 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001388 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001389 return 1;
1390}
Kailang Yangea1fb292008-08-26 12:58:38 +02001391
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001392/* Check the validity of ALC subsystem-id
1393 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1394static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001395{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001396 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001397 struct alc_spec *spec = codec->spec;
1398 snd_printd("realtek: "
1399 "Enable default setup for auto mode as fallback\n");
1400 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001401 }
Takashi Iwai21268962011-07-07 15:01:13 +02001402}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001403
Takashi Iwai41e41f12005-06-08 14:48:49 +02001404/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001405 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001406 */
1407
1408struct alc_pincfg {
1409 hda_nid_t nid;
1410 u32 val;
1411};
1412
Todd Broche1eb5f12010-12-06 11:19:51 -08001413struct alc_model_fixup {
1414 const int id;
1415 const char *name;
1416};
1417
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001418struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001419 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001420 bool chained;
1421 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001422 union {
1423 unsigned int sku;
1424 const struct alc_pincfg *pins;
1425 const struct hda_verb *verbs;
1426 void (*func)(struct hda_codec *codec,
1427 const struct alc_fixup *fix,
1428 int action);
1429 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001430};
1431
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001432enum {
1433 ALC_FIXUP_INVALID,
1434 ALC_FIXUP_SKU,
1435 ALC_FIXUP_PINS,
1436 ALC_FIXUP_VERBS,
1437 ALC_FIXUP_FUNC,
1438};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001439
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001440enum {
1441 ALC_FIXUP_ACT_PRE_PROBE,
1442 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001443 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001444};
1445
1446static void alc_apply_fixup(struct hda_codec *codec, int action)
1447{
1448 struct alc_spec *spec = codec->spec;
1449 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001450#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001451 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001452#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001453 int depth = 0;
1454
1455 if (!spec->fixup_list)
1456 return;
1457
1458 while (id >= 0) {
1459 const struct alc_fixup *fix = spec->fixup_list + id;
1460 const struct alc_pincfg *cfg;
1461
1462 switch (fix->type) {
1463 case ALC_FIXUP_SKU:
1464 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
Jesper Juhle53de8f2011-11-13 23:11:50 +01001465 break;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001466 snd_printdd(KERN_INFO "hda_codec: %s: "
1467 "Apply sku override for %s\n",
1468 codec->chip_name, modelname);
1469 spec->cdefine.sku_cfg = fix->v.sku;
1470 spec->cdefine.fixup = 1;
1471 break;
1472 case ALC_FIXUP_PINS:
1473 cfg = fix->v.pins;
1474 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1475 break;
1476 snd_printdd(KERN_INFO "hda_codec: %s: "
1477 "Apply pincfg for %s\n",
1478 codec->chip_name, modelname);
1479 for (; cfg->nid; cfg++)
1480 snd_hda_codec_set_pincfg(codec, cfg->nid,
1481 cfg->val);
1482 break;
1483 case ALC_FIXUP_VERBS:
1484 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1485 break;
1486 snd_printdd(KERN_INFO "hda_codec: %s: "
1487 "Apply fix-verbs for %s\n",
1488 codec->chip_name, modelname);
1489 add_verb(codec->spec, fix->v.verbs);
1490 break;
1491 case ALC_FIXUP_FUNC:
1492 if (!fix->v.func)
1493 break;
1494 snd_printdd(KERN_INFO "hda_codec: %s: "
1495 "Apply fix-func for %s\n",
1496 codec->chip_name, modelname);
1497 fix->v.func(codec, fix, action);
1498 break;
1499 default:
1500 snd_printk(KERN_ERR "hda_codec: %s: "
1501 "Invalid fixup type %d\n",
1502 codec->chip_name, fix->type);
1503 break;
1504 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001505 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001506 break;
1507 if (++depth > 10)
1508 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001509 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001510 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001511}
1512
Todd Broche1eb5f12010-12-06 11:19:51 -08001513static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001514 const struct alc_model_fixup *models,
1515 const struct snd_pci_quirk *quirk,
1516 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001517{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001518 struct alc_spec *spec = codec->spec;
Takashi Iwai596830e2011-11-09 15:06:45 +01001519 const struct snd_pci_quirk *q;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001520 int id = -1;
1521 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001522
Todd Broche1eb5f12010-12-06 11:19:51 -08001523 if (codec->modelname && models) {
1524 while (models->name) {
1525 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001526 id = models->id;
1527 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001528 break;
1529 }
1530 models++;
1531 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001532 }
1533 if (id < 0) {
Takashi Iwai596830e2011-11-09 15:06:45 +01001534 q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1535 if (q) {
1536 id = q->value;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001537#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwai596830e2011-11-09 15:06:45 +01001538 name = q->name;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001539#endif
1540 }
1541 }
Takashi Iwai596830e2011-11-09 15:06:45 +01001542 if (id < 0) {
1543 for (q = quirk; q->subvendor; q++) {
1544 unsigned int vendorid =
1545 q->subdevice | (q->subvendor << 16);
1546 if (vendorid == codec->subsystem_id) {
1547 id = q->value;
1548#ifdef CONFIG_SND_DEBUG_VERBOSE
1549 name = q->name;
1550#endif
1551 break;
1552 }
1553 }
1554 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001555
1556 spec->fixup_id = id;
1557 if (id >= 0) {
1558 spec->fixup_list = fixlist;
1559 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001560 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001561}
1562
Takashi Iwai1d045db2011-07-07 18:23:21 +02001563/*
1564 * COEF access helper functions
1565 */
Kailang Yang274693f2009-12-03 10:07:50 +01001566static int alc_read_coef_idx(struct hda_codec *codec,
1567 unsigned int coef_idx)
1568{
1569 unsigned int val;
1570 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1571 coef_idx);
1572 val = snd_hda_codec_read(codec, 0x20, 0,
1573 AC_VERB_GET_PROC_COEF, 0);
1574 return val;
1575}
1576
Kailang Yang977ddd62010-09-15 10:02:29 +02001577static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1578 unsigned int coef_val)
1579{
1580 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1581 coef_idx);
1582 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1583 coef_val);
1584}
1585
Takashi Iwai1bb7e432011-10-17 16:50:59 +02001586/* a special bypass for COEF 0; read the cached value at the second time */
1587static unsigned int alc_get_coef0(struct hda_codec *codec)
1588{
1589 struct alc_spec *spec = codec->spec;
1590 if (!spec->coef0)
1591 spec->coef0 = alc_read_coef_idx(codec, 0);
1592 return spec->coef0;
1593}
1594
Takashi Iwai1d045db2011-07-07 18:23:21 +02001595/*
1596 * Digital I/O handling
1597 */
1598
Takashi Iwai757899a2010-07-30 10:48:14 +02001599/* set right pin controls for digital I/O */
1600static void alc_auto_init_digital(struct hda_codec *codec)
1601{
1602 struct alc_spec *spec = codec->spec;
1603 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001604 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001605
1606 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1607 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001608 if (!pin)
1609 continue;
1610 snd_hda_codec_write(codec, pin, 0,
1611 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1612 if (!i)
1613 dac = spec->multiout.dig_out_nid;
1614 else
1615 dac = spec->slave_dig_outs[i - 1];
1616 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1617 continue;
1618 snd_hda_codec_write(codec, dac, 0,
1619 AC_VERB_SET_AMP_GAIN_MUTE,
1620 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001621 }
1622 pin = spec->autocfg.dig_in_pin;
1623 if (pin)
1624 snd_hda_codec_write(codec, pin, 0,
1625 AC_VERB_SET_PIN_WIDGET_CONTROL,
1626 PIN_IN);
1627}
1628
1629/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1630static void alc_auto_parse_digital(struct hda_codec *codec)
1631{
1632 struct alc_spec *spec = codec->spec;
Takashi Iwai51e41522011-11-03 16:54:06 +01001633 int i, err, nums;
Takashi Iwai757899a2010-07-30 10:48:14 +02001634 hda_nid_t dig_nid;
1635
1636 /* support multiple SPDIFs; the secondary is set up as a slave */
Takashi Iwai51e41522011-11-03 16:54:06 +01001637 nums = 0;
Takashi Iwai757899a2010-07-30 10:48:14 +02001638 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001639 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001640 err = snd_hda_get_connections(codec,
1641 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001642 conn, ARRAY_SIZE(conn));
Takashi Iwai51e41522011-11-03 16:54:06 +01001643 if (err <= 0)
Takashi Iwai757899a2010-07-30 10:48:14 +02001644 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001645 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai51e41522011-11-03 16:54:06 +01001646 if (!nums) {
Takashi Iwai757899a2010-07-30 10:48:14 +02001647 spec->multiout.dig_out_nid = dig_nid;
1648 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1649 } else {
1650 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
Takashi Iwai51e41522011-11-03 16:54:06 +01001651 if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
Takashi Iwai757899a2010-07-30 10:48:14 +02001652 break;
Takashi Iwai51e41522011-11-03 16:54:06 +01001653 spec->slave_dig_outs[nums - 1] = dig_nid;
Takashi Iwai757899a2010-07-30 10:48:14 +02001654 }
Takashi Iwai51e41522011-11-03 16:54:06 +01001655 nums++;
Takashi Iwai757899a2010-07-30 10:48:14 +02001656 }
1657
1658 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001659 dig_nid = codec->start_nid;
1660 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1661 unsigned int wcaps = get_wcaps(codec, dig_nid);
1662 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1663 continue;
1664 if (!(wcaps & AC_WCAP_DIGITAL))
1665 continue;
1666 if (!(wcaps & AC_WCAP_CONN_LIST))
1667 continue;
1668 err = get_connection_index(codec, dig_nid,
1669 spec->autocfg.dig_in_pin);
1670 if (err >= 0) {
1671 spec->dig_in_nid = dig_nid;
1672 break;
1673 }
1674 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001675 }
1676}
1677
Takashi Iwaif95474e2007-07-10 00:47:43 +02001678/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001679 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001680 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001681static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1682 struct snd_ctl_elem_info *uinfo)
1683{
1684 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1685 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001686 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001687 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001688
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001689 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001690 if (spec->vol_in_capsrc)
1691 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1692 else
1693 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1694 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001695 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001696 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001697 return err;
1698}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001700static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1701 unsigned int size, unsigned int __user *tlv)
1702{
1703 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1704 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001705 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001706 int err;
1707
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001708 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001709 if (spec->vol_in_capsrc)
1710 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1711 else
1712 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1713 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001714 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001715 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001716 return err;
1717}
1718
1719typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1720 struct snd_ctl_elem_value *ucontrol);
1721
1722static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1723 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001724 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001725{
1726 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1727 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001728 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001729
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001730 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001731 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001732 for (i = 0; i < spec->num_adc_nids; i++) {
1733 kcontrol->private_value =
1734 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1735 3, 0, HDA_INPUT);
1736 err = func(kcontrol, ucontrol);
1737 if (err < 0)
1738 goto error;
1739 }
1740 } else {
1741 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001742 if (spec->vol_in_capsrc)
1743 kcontrol->private_value =
1744 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1745 3, 0, HDA_OUTPUT);
1746 else
1747 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001748 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1749 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001750 err = func(kcontrol, ucontrol);
1751 }
1752 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001753 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001754 return err;
1755}
1756
1757static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1758 struct snd_ctl_elem_value *ucontrol)
1759{
1760 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001761 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001762}
1763
1764static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1765 struct snd_ctl_elem_value *ucontrol)
1766{
1767 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001768 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001769}
1770
1771/* capture mixer elements */
1772#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1773
1774static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1775 struct snd_ctl_elem_value *ucontrol)
1776{
1777 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001778 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001779}
1780
1781static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1782 struct snd_ctl_elem_value *ucontrol)
1783{
1784 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001785 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001786}
1787
Takashi Iwaia23b6882009-03-23 15:21:36 +01001788#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001789 { \
1790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1791 .name = "Capture Switch", \
1792 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1793 .count = num, \
1794 .info = alc_cap_sw_info, \
1795 .get = alc_cap_sw_get, \
1796 .put = alc_cap_sw_put, \
1797 }, \
1798 { \
1799 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1800 .name = "Capture Volume", \
1801 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1802 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1803 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1804 .count = num, \
1805 .info = alc_cap_vol_info, \
1806 .get = alc_cap_vol_get, \
1807 .put = alc_cap_vol_put, \
1808 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001809 }
1810
1811#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001812 { \
1813 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1814 /* .name = "Capture Source", */ \
1815 .name = "Input Source", \
1816 .count = num, \
1817 .info = alc_mux_enum_info, \
1818 .get = alc_mux_enum_get, \
1819 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001820 }
1821
1822#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001823static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001824 _DEFINE_CAPMIX(num), \
1825 _DEFINE_CAPSRC(num), \
1826 { } /* end */ \
1827}
1828
1829#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001830static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001831 _DEFINE_CAPMIX(num), \
1832 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001833}
1834
1835/* up to three ADCs */
1836DEFINE_CAPMIX(1);
1837DEFINE_CAPMIX(2);
1838DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001839DEFINE_CAPMIX_NOSRC(1);
1840DEFINE_CAPMIX_NOSRC(2);
1841DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001842
1843/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001844 * virtual master controls
1845 */
1846
1847/*
1848 * slave controls for virtual master
1849 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001850static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001851 "Front Playback Volume",
1852 "Surround Playback Volume",
1853 "Center Playback Volume",
1854 "LFE Playback Volume",
1855 "Side Playback Volume",
1856 "Headphone Playback Volume",
1857 "Speaker Playback Volume",
1858 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001859 "Line-Out Playback Volume",
Takashi Iwaib544d1e2012-02-03 11:56:35 +01001860 "CLFE Playback Volume",
1861 "Bass Speaker Playback Volume",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001862 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001863 NULL,
1864};
1865
Takashi Iwaiea734962011-01-17 11:29:34 +01001866static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001867 "Front Playback Switch",
1868 "Surround Playback Switch",
1869 "Center Playback Switch",
1870 "LFE Playback Switch",
1871 "Side Playback Switch",
1872 "Headphone Playback Switch",
1873 "Speaker Playback Switch",
1874 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001875 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001876 "Line-Out Playback Switch",
Takashi Iwaib544d1e2012-02-03 11:56:35 +01001877 "CLFE Playback Switch",
1878 "Bass Speaker Playback Switch",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001879 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001880 NULL,
1881};
1882
1883/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001884 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001886
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001887#define NID_MAPPING (-1)
1888
1889#define SUBDEV_SPEAKER_ (0 << 6)
1890#define SUBDEV_HP_ (1 << 6)
1891#define SUBDEV_LINE_ (2 << 6)
1892#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1893#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1894#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1895
Takashi Iwai603c4012008-07-30 15:01:44 +02001896static void alc_free_kctls(struct hda_codec *codec);
1897
Takashi Iwai67d634c2009-11-16 15:35:59 +01001898#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001899/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001900static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001901 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001902 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001903 { } /* end */
1904};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001905#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001906
Takashi Iwaif21d78e2012-01-19 12:10:29 +01001907static int __alc_build_controls(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908{
1909 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001910 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001911 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001912 int i, j, err;
1913 unsigned int u;
1914 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915
1916 for (i = 0; i < spec->num_mixers; i++) {
1917 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1918 if (err < 0)
1919 return err;
1920 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001921 if (spec->cap_mixer) {
1922 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1923 if (err < 0)
1924 return err;
1925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001927 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001928 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001929 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 if (err < 0)
1931 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001932 if (!spec->no_analog) {
1933 err = snd_hda_create_spdif_share_sw(codec,
1934 &spec->multiout);
1935 if (err < 0)
1936 return err;
1937 spec->multiout.share_spdif = 1;
1938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 }
1940 if (spec->dig_in_nid) {
1941 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1942 if (err < 0)
1943 return err;
1944 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001945
Takashi Iwai67d634c2009-11-16 15:35:59 +01001946#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001947 /* create beep controls if needed */
1948 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001949 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001950 for (knew = alc_beep_mixer; knew->name; knew++) {
1951 struct snd_kcontrol *kctl;
1952 kctl = snd_ctl_new1(knew, codec);
1953 if (!kctl)
1954 return -ENOMEM;
1955 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001956 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001957 if (err < 0)
1958 return err;
1959 }
1960 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001961#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001962
Takashi Iwai2134ea42008-01-10 16:53:55 +01001963 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001964 if (!spec->no_analog &&
1965 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001966 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001967 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001968 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001969 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001970 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001971 if (err < 0)
1972 return err;
1973 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001974 if (!spec->no_analog &&
1975 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001976 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1977 NULL, alc_slave_sws);
1978 if (err < 0)
1979 return err;
1980 }
1981
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001982 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001983 if (spec->capsrc_nids || spec->adc_nids) {
1984 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1985 if (!kctl)
1986 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1987 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai61071592011-11-23 07:52:15 +01001988 err = snd_hda_add_nid(codec, kctl, i,
1989 get_capsrc(spec, i));
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001990 if (err < 0)
1991 return err;
1992 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001993 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001994 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001995 const char *kname = kctl ? kctl->id.name : NULL;
1996 for (knew = spec->cap_mixer; knew->name; knew++) {
1997 if (kname && strcmp(knew->name, kname) == 0)
1998 continue;
1999 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
2000 for (i = 0; kctl && i < kctl->count; i++) {
2001 err = snd_hda_add_nid(codec, kctl, i,
2002 spec->adc_nids[i]);
2003 if (err < 0)
2004 return err;
2005 }
2006 }
2007 }
2008
2009 /* other nid->control mapping */
2010 for (i = 0; i < spec->num_mixers; i++) {
2011 for (knew = spec->mixers[i]; knew->name; knew++) {
2012 if (knew->iface != NID_MAPPING)
2013 continue;
2014 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
2015 if (kctl == NULL)
2016 continue;
2017 u = knew->subdevice;
2018 for (j = 0; j < 4; j++, u >>= 8) {
2019 nid = u & 0x3f;
2020 if (nid == 0)
2021 continue;
2022 switch (u & 0xc0) {
2023 case SUBDEV_SPEAKER_:
2024 nid = spec->autocfg.speaker_pins[nid];
2025 break;
2026 case SUBDEV_LINE_:
2027 nid = spec->autocfg.line_out_pins[nid];
2028 break;
2029 case SUBDEV_HP_:
2030 nid = spec->autocfg.hp_pins[nid];
2031 break;
2032 default:
2033 continue;
2034 }
2035 err = snd_hda_add_nid(codec, kctl, 0, nid);
2036 if (err < 0)
2037 return err;
2038 }
2039 u = knew->private_value;
2040 for (j = 0; j < 4; j++, u >>= 8) {
2041 nid = u & 0xff;
2042 if (nid == 0)
2043 continue;
2044 err = snd_hda_add_nid(codec, kctl, 0, nid);
2045 if (err < 0)
2046 return err;
2047 }
2048 }
2049 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01002050
2051 alc_free_kctls(codec); /* no longer needed */
2052
Takashi Iwaif21d78e2012-01-19 12:10:29 +01002053 return 0;
2054}
2055
2056static int alc_build_controls(struct hda_codec *codec)
2057{
2058 struct alc_spec *spec = codec->spec;
2059 int err = __alc_build_controls(codec);
Takashi Iwai01a61e12011-10-28 00:03:22 +02002060 if (err < 0)
2061 return err;
Takashi Iwaif21d78e2012-01-19 12:10:29 +01002062 return snd_hda_jack_add_kctls(codec, &spec->autocfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063}
2064
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002065
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002067 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002068 */
Takashi Iwai16ded522005-06-10 19:58:24 +02002069
Takashi Iwai584c0c42011-03-10 12:51:11 +01002070static void alc_init_special_input_src(struct hda_codec *codec);
2071
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072static int alc_init(struct hda_codec *codec)
2073{
2074 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002075 unsigned int i;
2076
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002077 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02002078 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002079
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002080 for (i = 0; i < spec->num_init_verbs; i++)
2081 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01002082 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002083
2084 if (spec->init_hook)
2085 spec->init_hook(codec);
2086
Takashi Iwai58701122011-01-13 15:41:45 +01002087 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2088
Takashi Iwai01a61e12011-10-28 00:03:22 +02002089 snd_hda_jack_report_sync(codec);
2090
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002091 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 return 0;
2093}
2094
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002095static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2096{
2097 struct alc_spec *spec = codec->spec;
2098
2099 if (spec->unsol_event)
2100 spec->unsol_event(codec, res);
2101}
2102
Takashi Iwaicb53c622007-08-10 17:21:45 +02002103#ifdef CONFIG_SND_HDA_POWER_SAVE
2104static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2105{
2106 struct alc_spec *spec = codec->spec;
2107 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2108}
2109#endif
2110
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111/*
2112 * Analog playback callbacks
2113 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002114static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002116 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117{
2118 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002119 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2120 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121}
2122
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002123static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 struct hda_codec *codec,
2125 unsigned int stream_tag,
2126 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002127 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128{
2129 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002130 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2131 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132}
2133
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002134static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002136 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137{
2138 struct alc_spec *spec = codec->spec;
2139 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2140}
2141
2142/*
2143 * Digital out
2144 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002145static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002147 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148{
2149 struct alc_spec *spec = codec->spec;
2150 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2151}
2152
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002153static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002154 struct hda_codec *codec,
2155 unsigned int stream_tag,
2156 unsigned int format,
2157 struct snd_pcm_substream *substream)
2158{
2159 struct alc_spec *spec = codec->spec;
2160 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2161 stream_tag, format, substream);
2162}
2163
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002164static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002165 struct hda_codec *codec,
2166 struct snd_pcm_substream *substream)
2167{
2168 struct alc_spec *spec = codec->spec;
2169 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2170}
2171
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002172static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002174 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175{
2176 struct alc_spec *spec = codec->spec;
2177 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2178}
2179
2180/*
2181 * Analog capture
2182 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002183static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 struct hda_codec *codec,
2185 unsigned int stream_tag,
2186 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002187 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188{
2189 struct alc_spec *spec = codec->spec;
2190
Takashi Iwai63300792008-01-24 15:31:36 +01002191 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 stream_tag, 0, format);
2193 return 0;
2194}
2195
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002196static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002198 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199{
2200 struct alc_spec *spec = codec->spec;
2201
Takashi Iwai888afa12008-03-18 09:57:50 +01002202 snd_hda_codec_cleanup_stream(codec,
2203 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 return 0;
2205}
2206
Takashi Iwai840b64c2010-07-13 22:49:01 +02002207/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002208static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002209 struct hda_codec *codec,
2210 unsigned int stream_tag,
2211 unsigned int format,
2212 struct snd_pcm_substream *substream)
2213{
2214 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002215 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002216 spec->cur_adc_stream_tag = stream_tag;
2217 spec->cur_adc_format = format;
2218 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2219 return 0;
2220}
2221
Takashi Iwai21268962011-07-07 15:01:13 +02002222static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002223 struct hda_codec *codec,
2224 struct snd_pcm_substream *substream)
2225{
2226 struct alc_spec *spec = codec->spec;
2227 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2228 spec->cur_adc = 0;
2229 return 0;
2230}
2231
Takashi Iwai21268962011-07-07 15:01:13 +02002232static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002233 .substreams = 1,
2234 .channels_min = 2,
2235 .channels_max = 2,
2236 .nid = 0, /* fill later */
2237 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002238 .prepare = dyn_adc_capture_pcm_prepare,
2239 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002240 },
2241};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
2243/*
2244 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002245static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 .substreams = 1,
2247 .channels_min = 2,
2248 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002249 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002251 .open = alc_playback_pcm_open,
2252 .prepare = alc_playback_pcm_prepare,
2253 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 },
2255};
2256
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002257static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002258 .substreams = 1,
2259 .channels_min = 2,
2260 .channels_max = 2,
2261 /* NID is set in alc_build_pcms */
2262};
2263
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002264static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002265 .substreams = 1,
2266 .channels_min = 2,
2267 .channels_max = 2,
2268 /* NID is set in alc_build_pcms */
2269};
2270
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002271static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002272 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 .channels_min = 2,
2274 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002275 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002277 .prepare = alc_alt_capture_pcm_prepare,
2278 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 },
2280};
2281
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002282static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 .substreams = 1,
2284 .channels_min = 2,
2285 .channels_max = 2,
2286 /* NID is set in alc_build_pcms */
2287 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002288 .open = alc_dig_playback_pcm_open,
2289 .close = alc_dig_playback_pcm_close,
2290 .prepare = alc_dig_playback_pcm_prepare,
2291 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 },
2293};
2294
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002295static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 .substreams = 1,
2297 .channels_min = 2,
2298 .channels_max = 2,
2299 /* NID is set in alc_build_pcms */
2300};
2301
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002302/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002303static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002304 .substreams = 0,
2305 .channels_min = 0,
2306 .channels_max = 0,
2307};
2308
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309static int alc_build_pcms(struct hda_codec *codec)
2310{
2311 struct alc_spec *spec = codec->spec;
2312 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002313 const struct hda_pcm_stream *p;
Takashi Iwai1fa17572011-11-02 21:30:51 +01002314 bool have_multi_adcs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 int i;
2316
2317 codec->num_pcms = 1;
2318 codec->pcm_info = info;
2319
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002320 if (spec->no_analog)
2321 goto skip_analog;
2322
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002323 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2324 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002326
Takashi Iwaieedec3d2012-02-06 10:24:04 +01002327 if (spec->multiout.num_dacs > 0) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002328 p = spec->stream_analog_playback;
2329 if (!p)
2330 p = &alc_pcm_analog_playback;
2331 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002332 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2333 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002334 if (spec->adc_nids) {
2335 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002336 if (!p) {
2337 if (spec->dyn_adc_switch)
2338 p = &dyn_adc_pcm_analog_capture;
2339 else
2340 p = &alc_pcm_analog_capture;
2341 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002342 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002343 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
Takashi Iwai4a471b72005-12-07 13:56:29 +01002346 if (spec->channel_mode) {
2347 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2348 for (i = 0; i < spec->num_channel_mode; i++) {
2349 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2350 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 }
2353 }
2354
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002355 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002356 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002358 snprintf(spec->stream_name_digital,
2359 sizeof(spec->stream_name_digital),
2360 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002361 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002362 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002363 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002365 if (spec->dig_out_type)
2366 info->pcm_type = spec->dig_out_type;
2367 else
2368 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002369 if (spec->multiout.dig_out_nid) {
2370 p = spec->stream_digital_playback;
2371 if (!p)
2372 p = &alc_pcm_digital_playback;
2373 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2375 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002376 if (spec->dig_in_nid) {
2377 p = spec->stream_digital_capture;
2378 if (!p)
2379 p = &alc_pcm_digital_capture;
2380 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2382 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002383 /* FIXME: do we need this for all Realtek codec models? */
2384 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 }
2386
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002387 if (spec->no_analog)
2388 return 0;
2389
Takashi Iwaie08a0072006-09-07 17:52:14 +02002390 /* If the use of more than one ADC is requested for the current
2391 * model, configure a second analog capture-only PCM.
2392 */
Takashi Iwai1fa17572011-11-02 21:30:51 +01002393 have_multi_adcs = (spec->num_adc_nids > 1) &&
2394 !spec->dyn_adc_switch && !spec->auto_mic &&
2395 (!spec->input_mux || spec->input_mux->num_items > 1);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002396 /* Additional Analaog capture for index #2 */
Takashi Iwai1fa17572011-11-02 21:30:51 +01002397 if (spec->alt_dac_nid || have_multi_adcs) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002398 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002399 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002400 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002401 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002402 p = spec->stream_analog_alt_playback;
2403 if (!p)
2404 p = &alc_pcm_analog_alt_playback;
2405 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002406 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2407 spec->alt_dac_nid;
2408 } else {
2409 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2410 alc_pcm_null_stream;
2411 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2412 }
Takashi Iwai1fa17572011-11-02 21:30:51 +01002413 if (have_multi_adcs) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002414 p = spec->stream_analog_alt_capture;
2415 if (!p)
2416 p = &alc_pcm_analog_alt_capture;
2417 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002418 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2419 spec->adc_nids[1];
2420 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2421 spec->num_adc_nids - 1;
2422 } else {
2423 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2424 alc_pcm_null_stream;
2425 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002426 }
2427 }
2428
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 return 0;
2430}
2431
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002432static inline void alc_shutup(struct hda_codec *codec)
2433{
Takashi Iwai1c716152011-04-07 10:37:16 +02002434 struct alc_spec *spec = codec->spec;
2435
2436 if (spec && spec->shutup)
2437 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002438 snd_hda_shutup_pins(codec);
2439}
2440
Takashi Iwai603c4012008-07-30 15:01:44 +02002441static void alc_free_kctls(struct hda_codec *codec)
2442{
2443 struct alc_spec *spec = codec->spec;
2444
2445 if (spec->kctls.list) {
2446 struct snd_kcontrol_new *kctl = spec->kctls.list;
2447 int i;
2448 for (i = 0; i < spec->kctls.used; i++)
2449 kfree(kctl[i].name);
2450 }
2451 snd_array_free(&spec->kctls);
2452}
2453
Takashi Iwai23c09b02011-08-19 09:05:35 +02002454static void alc_free_bind_ctls(struct hda_codec *codec)
2455{
2456 struct alc_spec *spec = codec->spec;
2457 if (spec->bind_ctls.list) {
2458 struct hda_bind_ctls **ctl = spec->bind_ctls.list;
2459 int i;
2460 for (i = 0; i < spec->bind_ctls.used; i++)
2461 kfree(ctl[i]);
2462 }
2463 snd_array_free(&spec->bind_ctls);
2464}
2465
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466static void alc_free(struct hda_codec *codec)
2467{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002468 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002469
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002470 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002471 return;
2472
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002473 alc_shutup(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002474 alc_free_kctls(codec);
Takashi Iwai23c09b02011-08-19 09:05:35 +02002475 alc_free_bind_ctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002476 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002477 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478}
2479
Hector Martinf5de24b2009-12-20 22:51:31 +01002480#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002481static void alc_power_eapd(struct hda_codec *codec)
2482{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002483 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002484}
2485
Hector Martinf5de24b2009-12-20 22:51:31 +01002486static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2487{
2488 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002489 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002490 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002491 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002492 return 0;
2493}
2494#endif
2495
Takashi Iwai2a439522011-07-26 09:52:50 +02002496#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002497static int alc_resume(struct hda_codec *codec)
2498{
Takashi Iwai1c716152011-04-07 10:37:16 +02002499 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002500 codec->patch_ops.init(codec);
2501 snd_hda_codec_resume_amp(codec);
2502 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002503 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002504 return 0;
2505}
Takashi Iwaie044c392008-10-27 16:56:24 +01002506#endif
2507
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508/*
2509 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002510static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 .build_controls = alc_build_controls,
2512 .build_pcms = alc_build_pcms,
2513 .init = alc_init,
2514 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002515 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002516#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002517 .resume = alc_resume,
2518#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002519#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002520 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002521 .check_power_status = alc_check_power_status,
2522#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002523 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524};
2525
Kailang Yangc027ddc2010-03-19 11:33:06 +01002526/* replace the codec chip_name with the given string */
2527static int alc_codec_rename(struct hda_codec *codec, const char *name)
2528{
2529 kfree(codec->chip_name);
2530 codec->chip_name = kstrdup(name, GFP_KERNEL);
2531 if (!codec->chip_name) {
2532 alc_free(codec);
2533 return -ENOMEM;
2534 }
2535 return 0;
2536}
2537
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002538/*
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002539 * Rename codecs appropriately from COEF value
2540 */
2541struct alc_codec_rename_table {
2542 unsigned int vendor_id;
2543 unsigned short coef_mask;
2544 unsigned short coef_bits;
2545 const char *name;
2546};
2547
2548static struct alc_codec_rename_table rename_tbl[] = {
2549 { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
2550 { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
2551 { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" },
2552 { 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" },
2553 { 0x10ec0269, 0xffff, 0xa023, "ALC259" },
2554 { 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
2555 { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
2556 { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
2557 { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
2558 { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
2559 { 0x10ec0899, 0x2000, 0x2000, "ALC899" },
2560 { 0x10ec0892, 0xffff, 0x8020, "ALC661" },
2561 { 0x10ec0892, 0xffff, 0x8011, "ALC661" },
2562 { 0x10ec0892, 0xffff, 0x4011, "ALC656" },
2563 { } /* terminator */
2564};
2565
2566static int alc_codec_rename_from_preset(struct hda_codec *codec)
2567{
2568 const struct alc_codec_rename_table *p;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002569
2570 for (p = rename_tbl; p->vendor_id; p++) {
2571 if (p->vendor_id != codec->vendor_id)
2572 continue;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02002573 if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002574 return alc_codec_rename(codec, p->name);
2575 }
2576 return 0;
2577}
2578
2579/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002580 * Automatic parse of I/O pins from the BIOS configuration
2581 */
2582
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002583enum {
2584 ALC_CTL_WIDGET_VOL,
2585 ALC_CTL_WIDGET_MUTE,
2586 ALC_CTL_BIND_MUTE,
Takashi Iwai23c09b02011-08-19 09:05:35 +02002587 ALC_CTL_BIND_VOL,
2588 ALC_CTL_BIND_SW,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002589};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002590static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002591 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2592 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002593 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwai23c09b02011-08-19 09:05:35 +02002594 HDA_BIND_VOL(NULL, 0),
2595 HDA_BIND_SW(NULL, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002596};
2597
2598/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002599static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002600 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002601{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002602 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002603
Takashi Iwaice764ab2011-04-27 16:35:23 +02002604 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002605 if (!knew)
2606 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002607 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002608 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002609 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002610 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002611 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002612 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002613 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002614 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002615 return 0;
2616}
2617
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002618static int add_control_with_pfx(struct alc_spec *spec, int type,
2619 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002620 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002621{
2622 char name[32];
2623 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002624 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002625}
2626
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002627#define add_pb_vol_ctrl(spec, type, pfx, val) \
2628 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2629#define add_pb_sw_ctrl(spec, type, pfx, val) \
2630 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2631#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2632 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2633#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2634 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002635
Takashi Iwai23c09b02011-08-19 09:05:35 +02002636static const char * const channel_name[4] = {
2637 "Front", "Surround", "CLFE", "Side"
2638};
2639
Takashi Iwai6843ca12011-06-24 11:03:58 +02002640static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2641 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002642{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002643 struct auto_pin_cfg *cfg = &spec->autocfg;
2644
Takashi Iwai6843ca12011-06-24 11:03:58 +02002645 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002646 if (cfg->line_outs == 1 && !spec->multi_ios &&
2647 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002648 return "Master";
2649
2650 switch (cfg->line_out_type) {
2651 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002652 if (cfg->line_outs == 1)
2653 return "Speaker";
Takashi Iwaifbabc242011-12-07 17:14:20 +01002654 if (cfg->line_outs == 2)
2655 return ch ? "Bass Speaker" : "Speaker";
David Henningssonebbeb3d2011-03-04 14:08:30 +01002656 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002657 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002658 /* for multi-io case, only the primary out */
2659 if (ch && spec->multi_ios)
2660 break;
2661 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002662 return "Headphone";
2663 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002664 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002665 return "PCM";
2666 break;
2667 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02002668 if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name)))
2669 return "PCM";
2670
2671 return channel_name[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002672}
2673
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002674/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002675static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002676 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002677 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002678{
Kailang Yangdf694da2005-12-05 19:42:22 +01002679 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002680
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002681 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002682 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2683 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002684 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002685 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002686 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2687 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002688 return err;
2689 return 0;
2690}
2691
Takashi Iwai05f5f472009-08-25 13:10:18 +02002692static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002693{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002694 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2695 return (pincap & AC_PINCAP_IN) != 0;
2696}
2697
Takashi Iwai1d045db2011-07-07 18:23:21 +02002698/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002699static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002700{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002701 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002702 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002703 hda_nid_t *adc_nids = spec->private_adc_nids;
2704 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2705 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
Takashi Iwaib7821702011-07-06 15:12:46 +02002706 int i, nums = 0;
2707
Takashi Iwai24de1832011-11-07 17:13:39 +01002708 if (spec->shared_mic_hp)
2709 max_nums = 1; /* no multi streams with the shared HP/mic */
2710
Takashi Iwaib7821702011-07-06 15:12:46 +02002711 nid = codec->start_nid;
2712 for (i = 0; i < codec->num_nodes; i++, nid++) {
2713 hda_nid_t src;
2714 const hda_nid_t *list;
2715 unsigned int caps = get_wcaps(codec, nid);
2716 int type = get_wcaps_type(caps);
2717
2718 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2719 continue;
2720 adc_nids[nums] = nid;
2721 cap_nids[nums] = nid;
2722 src = nid;
2723 for (;;) {
2724 int n;
2725 type = get_wcaps_type(get_wcaps(codec, src));
2726 if (type == AC_WID_PIN)
2727 break;
2728 if (type == AC_WID_AUD_SEL) {
2729 cap_nids[nums] = src;
2730 break;
2731 }
2732 n = snd_hda_get_conn_list(codec, src, &list);
2733 if (n > 1) {
2734 cap_nids[nums] = src;
2735 break;
2736 } else if (n != 1)
2737 break;
2738 src = *list;
2739 }
2740 if (++nums >= max_nums)
2741 break;
2742 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002743 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002744 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002745 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002746 return nums;
2747}
2748
Takashi Iwai05f5f472009-08-25 13:10:18 +02002749/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002750static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002751{
2752 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002753 const struct auto_pin_cfg *cfg = &spec->autocfg;
2754 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002755 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002756 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002757 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002758 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002759
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002760 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002761 if (num_adcs < 0)
2762 return 0;
2763
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002764 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002765 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002766 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002767
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002768 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002769 if (!alc_is_input_pin(codec, pin))
2770 continue;
2771
David Henningsson5322bf22011-01-05 11:03:56 +01002772 label = hda_get_autocfg_input_label(codec, cfg, i);
Takashi Iwai24de1832011-11-07 17:13:39 +01002773 if (spec->shared_mic_hp && !strcmp(label, "Misc"))
2774 label = "Headphone Mic";
David Henningsson5322bf22011-01-05 11:03:56 +01002775 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002776 type_idx++;
2777 else
2778 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002779 prev_label = label;
2780
Takashi Iwai05f5f472009-08-25 13:10:18 +02002781 if (mixer) {
2782 idx = get_connection_index(codec, mixer, pin);
2783 if (idx >= 0) {
2784 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002785 label, type_idx,
2786 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002787 if (err < 0)
2788 return err;
2789 }
2790 }
2791
Takashi Iwaib7821702011-07-06 15:12:46 +02002792 for (c = 0; c < num_adcs; c++) {
Takashi Iwai61071592011-11-23 07:52:15 +01002793 hda_nid_t cap = get_capsrc(spec, c);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002794 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002795 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002796 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002797 snd_hda_add_imux_item(imux, label, idx, NULL);
2798 break;
2799 }
2800 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002801 }
Takashi Iwai21268962011-07-07 15:01:13 +02002802
2803 spec->num_mux_defs = 1;
2804 spec->input_mux = imux;
2805
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002806 return 0;
2807}
2808
Takashi Iwai24de1832011-11-07 17:13:39 +01002809/* create a shared input with the headphone out */
2810static int alc_auto_create_shared_input(struct hda_codec *codec)
2811{
2812 struct alc_spec *spec = codec->spec;
2813 struct auto_pin_cfg *cfg = &spec->autocfg;
2814 unsigned int defcfg;
2815 hda_nid_t nid;
2816
2817 /* only one internal input pin? */
2818 if (cfg->num_inputs != 1)
2819 return 0;
2820 defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2821 if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2822 return 0;
2823
2824 if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
2825 nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
2826 else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
2827 nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
2828 else
2829 return 0; /* both not available */
2830
2831 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2832 return 0; /* no input */
2833
2834 cfg->inputs[1].pin = nid;
2835 cfg->inputs[1].type = AUTO_PIN_MIC;
2836 cfg->num_inputs = 2;
2837 spec->shared_mic_hp = 1;
2838 snd_printdd("realtek: Enable shared I/O jack on NID 0x%x\n", nid);
2839 return 0;
2840}
2841
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002842static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2843 unsigned int pin_type)
2844{
2845 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2846 pin_type);
2847 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002848 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2849 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002850 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002851}
2852
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002853static int get_pin_type(int line_out_type)
2854{
2855 if (line_out_type == AUTO_PIN_HP_OUT)
2856 return PIN_HP;
2857 else
2858 return PIN_OUT;
2859}
2860
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002861static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002862{
2863 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002864 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002865 int i;
2866
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002867 for (i = 0; i < cfg->num_inputs; i++) {
2868 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002869 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002870 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002871 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002872 snd_hda_codec_write(codec, nid, 0,
2873 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002874 AMP_OUT_MUTE);
2875 }
2876 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002877
2878 /* mute all loopback inputs */
2879 if (spec->mixer_nid) {
2880 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2881 for (i = 0; i < nums; i++)
2882 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2883 AC_VERB_SET_AMP_GAIN_MUTE,
2884 AMP_IN_MUTE(i));
2885 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002886}
2887
Takashi Iwai7085ec12009-10-02 09:03:58 +02002888/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002889static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002890{
Takashi Iwai604401a2011-04-27 15:14:23 +02002891 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002892 int i, num;
2893
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002894 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2895 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002896 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2897 for (i = 0; i < num; i++) {
2898 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2899 return list[i];
2900 }
2901 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002902}
2903
Takashi Iwai604401a2011-04-27 15:14:23 +02002904/* go down to the selector widget before the mixer */
2905static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2906{
2907 hda_nid_t srcs[5];
2908 int num = snd_hda_get_connections(codec, pin, srcs,
2909 ARRAY_SIZE(srcs));
2910 if (num != 1 ||
2911 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2912 return pin;
2913 return srcs[0];
2914}
2915
Takashi Iwai7085ec12009-10-02 09:03:58 +02002916/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002917static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002918 hda_nid_t dac)
2919{
David Henningssoncc1c4522010-11-24 14:17:47 +01002920 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002921 int i, num;
2922
Takashi Iwai604401a2011-04-27 15:14:23 +02002923 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002924 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2925 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002926 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002927 return mix[i];
2928 }
2929 return 0;
2930}
2931
Takashi Iwaice764ab2011-04-27 16:35:23 +02002932/* select the connection from pin to DAC if needed */
2933static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2934 hda_nid_t dac)
2935{
2936 hda_nid_t mix[5];
2937 int i, num;
2938
2939 pin = alc_go_down_to_selector(codec, pin);
2940 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2941 if (num < 2)
2942 return 0;
2943 for (i = 0; i < num; i++) {
2944 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2945 snd_hda_codec_update_cache(codec, pin, 0,
2946 AC_VERB_SET_CONNECT_SEL, i);
2947 return 0;
2948 }
2949 }
2950 return 0;
2951}
2952
Takashi Iwai7085ec12009-10-02 09:03:58 +02002953/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002954static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002955{
2956 struct alc_spec *spec = codec->spec;
2957 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002958 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002959
Takashi Iwai604401a2011-04-27 15:14:23 +02002960 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002961 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002962 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002963 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002964 if (!nid)
2965 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002966 if (found_in_nid_list(nid, spec->multiout.dac_nids,
Takashi Iwai0a34b422011-12-07 17:20:30 +01002967 ARRAY_SIZE(spec->private_dac_nids)))
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002968 continue;
Takashi Iwaic2674682011-08-24 17:57:44 +02002969 if (found_in_nid_list(nid, spec->multiout.hp_out_nid,
2970 ARRAY_SIZE(spec->multiout.hp_out_nid)))
2971 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002972 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2973 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2974 continue;
2975 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002976 }
2977 return 0;
2978}
2979
Takashi Iwai07b18f62011-11-10 15:42:54 +01002980/* check whether the DAC is reachable from the pin */
2981static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
2982 hda_nid_t pin, hda_nid_t dac)
2983{
2984 hda_nid_t srcs[5];
2985 int i, num;
2986
2987 pin = alc_go_down_to_selector(codec, pin);
2988 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
2989 for (i = 0; i < num; i++) {
2990 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
2991 if (nid == dac)
2992 return true;
2993 }
2994 return false;
2995}
2996
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002997static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2998{
2999 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
3000 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
3001 return alc_auto_look_for_dac(codec, pin);
3002 return 0;
3003}
3004
Takashi Iwai0a34b422011-12-07 17:20:30 +01003005/* return 0 if no possible DAC is found, 1 if one or more found */
Takashi Iwaic2674682011-08-24 17:57:44 +02003006static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
3007 const hda_nid_t *pins, hda_nid_t *dacs)
3008{
3009 int i;
3010
3011 if (num_outs && !dacs[0]) {
3012 dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
3013 if (!dacs[0])
3014 return 0;
3015 }
3016
3017 for (i = 1; i < num_outs; i++)
3018 dacs[i] = get_dac_if_single(codec, pins[i]);
3019 for (i = 1; i < num_outs; i++) {
3020 if (!dacs[i])
3021 dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
3022 }
Takashi Iwai0a34b422011-12-07 17:20:30 +01003023 return 1;
Takashi Iwaic2674682011-08-24 17:57:44 +02003024}
3025
3026static int alc_auto_fill_multi_ios(struct hda_codec *codec,
Takashi Iwai07b18f62011-11-10 15:42:54 +01003027 unsigned int location, int offset);
David Henningssonfde48a12011-12-09 18:27:42 +08003028static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
3029 hda_nid_t pin, hda_nid_t dac);
Takashi Iwaic2674682011-08-24 17:57:44 +02003030
Takashi Iwai7085ec12009-10-02 09:03:58 +02003031/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02003032static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003033{
3034 struct alc_spec *spec = codec->spec;
Takashi Iwai0a34b422011-12-07 17:20:30 +01003035 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai07b18f62011-11-10 15:42:54 +01003036 unsigned int location, defcfg;
3037 int num_pins;
Takashi Iwai350434e2011-06-30 21:29:12 +02003038 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003039 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003040
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003041 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02003042 /* set num_dacs once to full for alc_auto_look_for_dac() */
3043 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwaie23832a2011-08-23 18:16:56 +02003044 spec->multiout.hp_out_nid[0] = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003045 spec->multiout.extra_out_nid[0] = 0;
3046 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
3047 spec->multiout.dac_nids = spec->private_dac_nids;
Takashi Iwai0a34b422011-12-07 17:20:30 +01003048 spec->multi_ios = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003049
3050 /* fill hard-wired DACs first */
3051 if (!redone) {
3052 for (i = 0; i < cfg->line_outs; i++)
3053 spec->private_dac_nids[i] =
3054 get_dac_if_single(codec, cfg->line_out_pins[i]);
3055 if (cfg->hp_outs)
Takashi Iwaie23832a2011-08-23 18:16:56 +02003056 spec->multiout.hp_out_nid[0] =
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003057 get_dac_if_single(codec, cfg->hp_pins[0]);
3058 if (cfg->speaker_outs)
3059 spec->multiout.extra_out_nid[0] =
3060 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003061 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003062
3063 for (i = 0; i < cfg->line_outs; i++) {
3064 hda_nid_t pin = cfg->line_out_pins[i];
3065 if (spec->private_dac_nids[i])
3066 continue;
3067 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
3068 if (!spec->private_dac_nids[i] && !redone) {
3069 /* if we can't find primary DACs, re-probe without
3070 * checking the hard-wired DACs
3071 */
3072 redone = true;
3073 goto again;
3074 }
3075 }
3076
Takashi Iwai8f398ae2011-07-23 18:57:11 +02003077 /* re-count num_dacs and squash invalid entries */
3078 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003079 for (i = 0; i < cfg->line_outs; i++) {
3080 if (spec->private_dac_nids[i])
3081 spec->multiout.num_dacs++;
Takashi Iwai0a34b422011-12-07 17:20:30 +01003082 else {
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003083 memmove(spec->private_dac_nids + i,
3084 spec->private_dac_nids + i + 1,
3085 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
Takashi Iwai0a34b422011-12-07 17:20:30 +01003086 spec->private_dac_nids[cfg->line_outs - 1] = 0;
3087 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003088 }
3089
Takashi Iwaic2674682011-08-24 17:57:44 +02003090 if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3091 /* try to fill multi-io first */
Takashi Iwaic2674682011-08-24 17:57:44 +02003092 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3093 location = get_defcfg_location(defcfg);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003094
Takashi Iwai07b18f62011-11-10 15:42:54 +01003095 num_pins = alc_auto_fill_multi_ios(codec, location, 0);
Takashi Iwaic2674682011-08-24 17:57:44 +02003096 if (num_pins > 0) {
3097 spec->multi_ios = num_pins;
3098 spec->ext_channel_count = 2;
3099 spec->multiout.num_dacs = num_pins + 1;
3100 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02003101 }
Takashi Iwaic2674682011-08-24 17:57:44 +02003102
Takashi Iwai716eef02011-10-21 15:07:42 +02003103 if (cfg->line_out_type != AUTO_PIN_HP_OUT)
3104 alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins,
Takashi Iwaic2674682011-08-24 17:57:44 +02003105 spec->multiout.hp_out_nid);
Takashi Iwai0a34b422011-12-07 17:20:30 +01003106 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3107 int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
3108 cfg->speaker_pins,
3109 spec->multiout.extra_out_nid);
3110 /* if no speaker volume is assigned, try again as the primary
3111 * output
3112 */
3113 if (!err && cfg->speaker_outs > 0 &&
3114 cfg->line_out_type == AUTO_PIN_HP_OUT) {
3115 cfg->hp_outs = cfg->line_outs;
3116 memcpy(cfg->hp_pins, cfg->line_out_pins,
3117 sizeof(cfg->hp_pins));
3118 cfg->line_outs = cfg->speaker_outs;
3119 memcpy(cfg->line_out_pins, cfg->speaker_pins,
3120 sizeof(cfg->speaker_pins));
3121 cfg->speaker_outs = 0;
3122 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3123 cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3124 redone = false;
3125 goto again;
3126 }
3127 }
Takashi Iwaic2674682011-08-24 17:57:44 +02003128
Takashi Iwai07b18f62011-11-10 15:42:54 +01003129 if (!spec->multi_ios &&
3130 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
3131 cfg->hp_outs) {
3132 /* try multi-ios with HP + inputs */
3133 defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]);
3134 location = get_defcfg_location(defcfg);
3135
3136 num_pins = alc_auto_fill_multi_ios(codec, location, 1);
3137 if (num_pins > 0) {
3138 spec->multi_ios = num_pins;
3139 spec->ext_channel_count = 2;
3140 spec->multiout.num_dacs = num_pins + 1;
3141 }
3142 }
3143
David Henningssonfde48a12011-12-09 18:27:42 +08003144 if (cfg->line_out_pins[0])
3145 spec->vmaster_nid =
3146 alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0],
3147 spec->multiout.dac_nids[0]);
Takashi Iwai23c09b02011-08-19 09:05:35 +02003148 return 0;
3149}
3150
Takashi Iwai527e4d72011-10-27 16:33:27 +02003151static inline unsigned int get_ctl_pos(unsigned int data)
3152{
3153 hda_nid_t nid = get_amp_nid_(data);
Takashi Iwaic14c95f2012-02-16 16:38:07 +01003154 unsigned int dir;
3155 if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
3156 return 0;
3157 dir = get_amp_direction_(data);
Takashi Iwai527e4d72011-10-27 16:33:27 +02003158 return (nid << 1) | dir;
3159}
3160
3161#define is_ctl_used(bits, data) \
3162 test_bit(get_ctl_pos(data), bits)
3163#define mark_ctl_usage(bits, data) \
3164 set_bit(get_ctl_pos(data), bits)
3165
Takashi Iwai343a04b2011-07-06 14:28:39 +02003166static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02003167 const char *pfx, int cidx,
3168 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003169{
Takashi Iwai527e4d72011-10-27 16:33:27 +02003170 struct alc_spec *spec = codec->spec;
3171 unsigned int val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003172 if (!nid)
3173 return 0;
Takashi Iwai527e4d72011-10-27 16:33:27 +02003174 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
3175 if (is_ctl_used(spec->vol_ctls, val) && chs != 2) /* exclude LFE */
3176 return 0;
3177 mark_ctl_usage(spec->vol_ctls, val);
Takashi Iwai97aaab72011-07-06 14:02:55 +02003178 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
Takashi Iwai527e4d72011-10-27 16:33:27 +02003179 val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003180}
3181
Takashi Iwaie29d3772011-11-14 17:13:23 +01003182static int alc_auto_add_stereo_vol(struct hda_codec *codec,
3183 const char *pfx, int cidx,
3184 hda_nid_t nid)
3185{
3186 int chs = 1;
3187 if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
3188 chs = 3;
3189 return alc_auto_add_vol_ctl(codec, pfx, cidx, nid, chs);
3190}
Takashi Iwai97aaab72011-07-06 14:02:55 +02003191
3192/* create a mute-switch for the given mixer widget;
3193 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
3194 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02003195static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02003196 const char *pfx, int cidx,
3197 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003198{
Takashi Iwai527e4d72011-10-27 16:33:27 +02003199 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003200 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02003201 int type;
3202 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003203 if (!nid)
3204 return 0;
3205 wid_type = get_wcaps_type(get_wcaps(codec, nid));
3206 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
3207 type = ALC_CTL_WIDGET_MUTE;
3208 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
3209 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02003210 type = ALC_CTL_WIDGET_MUTE;
3211 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
3212 } else {
3213 type = ALC_CTL_BIND_MUTE;
3214 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
3215 }
Takashi Iwai527e4d72011-10-27 16:33:27 +02003216 if (is_ctl_used(spec->sw_ctls, val) && chs != 2) /* exclude LFE */
3217 return 0;
3218 mark_ctl_usage(spec->sw_ctls, val);
Takashi Iwai97aaab72011-07-06 14:02:55 +02003219 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003220}
3221
Takashi Iwaie29d3772011-11-14 17:13:23 +01003222static int alc_auto_add_stereo_sw(struct hda_codec *codec, const char *pfx,
3223 int cidx, hda_nid_t nid)
3224{
3225 int chs = 1;
3226 if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
3227 chs = 3;
3228 return alc_auto_add_sw_ctl(codec, pfx, cidx, nid, chs);
3229}
Takashi Iwai7085ec12009-10-02 09:03:58 +02003230
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003231static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
3232 hda_nid_t pin, hda_nid_t dac)
3233{
3234 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
3235 if (nid_has_mute(codec, pin, HDA_OUTPUT))
3236 return pin;
3237 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
3238 return mix;
3239 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
3240 return dac;
3241 return 0;
3242}
3243
3244static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
3245 hda_nid_t pin, hda_nid_t dac)
3246{
3247 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
3248 if (nid_has_volume(codec, dac, HDA_OUTPUT))
3249 return dac;
3250 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
3251 return mix;
3252 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
3253 return pin;
3254 return 0;
3255}
3256
Takashi Iwai7085ec12009-10-02 09:03:58 +02003257/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02003258static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003259 const struct auto_pin_cfg *cfg)
3260{
3261 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003262 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003263
Takashi Iwaice764ab2011-04-27 16:35:23 +02003264 noutputs = cfg->line_outs;
Takashi Iwaib90bf1d2012-01-19 11:42:55 +01003265 if (spec->multi_ios > 0 && cfg->line_outs < 3)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003266 noutputs += spec->multi_ios;
3267
3268 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02003269 const char *name;
3270 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003271 hda_nid_t dac, pin;
3272 hda_nid_t sw, vol;
3273
3274 dac = spec->multiout.dac_nids[i];
3275 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003276 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003277 if (i >= cfg->line_outs)
3278 pin = spec->multi_io[i - 1].pin;
3279 else
3280 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003281
3282 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3283 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02003284 name = alc_get_line_out_pfx(spec, i, true, &index);
Takashi Iwai9c4e84d2011-08-24 17:27:52 +02003285 if (!name || !strcmp(name, "CLFE")) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003286 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003287 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003288 if (err < 0)
3289 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003290 err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003291 if (err < 0)
3292 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003293 err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003294 if (err < 0)
3295 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003296 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003297 if (err < 0)
3298 return err;
3299 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003300 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003301 if (err < 0)
3302 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003303 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003304 if (err < 0)
3305 return err;
3306 }
3307 }
3308 return 0;
3309}
3310
Takashi Iwai343a04b2011-07-06 14:28:39 +02003311static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai766ddee2011-12-07 16:55:19 +01003312 hda_nid_t dac, const char *pfx,
3313 int cidx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003314{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003315 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003316 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003317 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003318
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003319 if (!dac) {
Takashi Iwai527e4d72011-10-27 16:33:27 +02003320 unsigned int val;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003321 /* the corresponding DAC is already occupied */
3322 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
3323 return 0; /* no way */
3324 /* create a switch only */
Takashi Iwai527e4d72011-10-27 16:33:27 +02003325 val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT);
3326 if (is_ctl_used(spec->sw_ctls, val))
3327 return 0; /* already created */
3328 mark_ctl_usage(spec->sw_ctls, val);
Takashi Iwai766ddee2011-12-07 16:55:19 +01003329 return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003330 }
3331
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003332 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3333 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai766ddee2011-12-07 16:55:19 +01003334 err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003335 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003336 return err;
Takashi Iwai766ddee2011-12-07 16:55:19 +01003337 err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003338 if (err < 0)
3339 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003340 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003341}
3342
Takashi Iwai23c09b02011-08-19 09:05:35 +02003343static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
3344 unsigned int nums,
3345 struct hda_ctl_ops *ops)
3346{
3347 struct alc_spec *spec = codec->spec;
3348 struct hda_bind_ctls **ctlp, *ctl;
3349 snd_array_init(&spec->bind_ctls, sizeof(ctl), 8);
3350 ctlp = snd_array_new(&spec->bind_ctls);
3351 if (!ctlp)
3352 return NULL;
3353 ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL);
3354 *ctlp = ctl;
3355 if (ctl)
3356 ctl->ops = ops;
3357 return ctl;
3358}
3359
3360/* add playback controls for speaker and HP outputs */
3361static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
3362 const hda_nid_t *pins,
3363 const hda_nid_t *dacs,
3364 const char *pfx)
3365{
3366 struct alc_spec *spec = codec->spec;
3367 struct hda_bind_ctls *ctl;
3368 char name[32];
3369 int i, n, err;
3370
3371 if (!num_pins || !pins[0])
3372 return 0;
3373
Takashi Iwai527e4d72011-10-27 16:33:27 +02003374 if (num_pins == 1) {
3375 hda_nid_t dac = *dacs;
3376 if (!dac)
3377 dac = spec->multiout.dac_nids[0];
Takashi Iwai766ddee2011-12-07 16:55:19 +01003378 return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0);
Takashi Iwai527e4d72011-10-27 16:33:27 +02003379 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02003380
3381 if (dacs[num_pins - 1]) {
3382 /* OK, we have a multi-output system with individual volumes */
3383 for (i = 0; i < num_pins; i++) {
Takashi Iwai766ddee2011-12-07 16:55:19 +01003384 if (num_pins >= 3) {
3385 snprintf(name, sizeof(name), "%s %s",
3386 pfx, channel_name[i]);
3387 err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
3388 name, 0);
3389 } else {
3390 err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
3391 pfx, i);
3392 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02003393 if (err < 0)
3394 return err;
3395 }
3396 return 0;
3397 }
3398
3399 /* Let's create a bind-controls */
3400 ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw);
3401 if (!ctl)
3402 return -ENOMEM;
3403 n = 0;
3404 for (i = 0; i < num_pins; i++) {
3405 if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP)
3406 ctl->values[n++] =
3407 HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT);
3408 }
3409 if (n) {
3410 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
3411 err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl);
3412 if (err < 0)
3413 return err;
3414 }
3415
3416 ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
3417 if (!ctl)
3418 return -ENOMEM;
3419 n = 0;
3420 for (i = 0; i < num_pins; i++) {
3421 hda_nid_t vol;
3422 if (!pins[i] || !dacs[i])
3423 continue;
3424 vol = alc_look_for_out_vol_nid(codec, pins[i], dacs[i]);
3425 if (vol)
3426 ctl->values[n++] =
3427 HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT);
3428 }
3429 if (n) {
3430 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
3431 err = add_control(spec, ALC_CTL_BIND_VOL, name, 0, (long)ctl);
3432 if (err < 0)
3433 return err;
3434 }
3435 return 0;
3436}
3437
Takashi Iwai343a04b2011-07-06 14:28:39 +02003438static int alc_auto_create_hp_out(struct hda_codec *codec)
3439{
3440 struct alc_spec *spec = codec->spec;
Takashi Iwaie23832a2011-08-23 18:16:56 +02003441 return alc_auto_create_extra_outs(codec, spec->autocfg.hp_outs,
3442 spec->autocfg.hp_pins,
3443 spec->multiout.hp_out_nid,
3444 "Headphone");
Takashi Iwai343a04b2011-07-06 14:28:39 +02003445}
3446
3447static int alc_auto_create_speaker_out(struct hda_codec *codec)
3448{
3449 struct alc_spec *spec = codec->spec;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003450 return alc_auto_create_extra_outs(codec, spec->autocfg.speaker_outs,
3451 spec->autocfg.speaker_pins,
3452 spec->multiout.extra_out_nid,
3453 "Speaker");
Takashi Iwai343a04b2011-07-06 14:28:39 +02003454}
3455
Takashi Iwai343a04b2011-07-06 14:28:39 +02003456static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003457 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003458 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003459{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003460 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003461 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003462 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003463
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003464 alc_set_pin_output(codec, pin, pin_type);
3465 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003466 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003467 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003468 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003469 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003470 mix = srcs[i];
3471 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003472 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003473 if (!mix)
3474 return;
3475
3476 /* need the manual connection? */
3477 if (num > 1)
3478 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3479 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003480 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3481 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003482 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003483 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003484 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003485 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003486 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003487 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3488 if (nid)
3489 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3490 AMP_OUT_ZERO);
Takashi Iwai43dea222011-11-06 11:25:34 +01003491
3492 /* unmute DAC if it's not assigned to a mixer */
3493 nid = alc_look_for_out_mute_nid(codec, pin, dac);
3494 if (nid == mix && nid_has_mute(codec, dac, HDA_OUTPUT))
3495 snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3496 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003497}
3498
Takashi Iwai343a04b2011-07-06 14:28:39 +02003499static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003500{
3501 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003502 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003503 int i;
3504
3505 for (i = 0; i <= HDA_SIDE; i++) {
3506 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3507 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003508 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003509 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003510 }
3511}
3512
Takashi Iwai343a04b2011-07-06 14:28:39 +02003513static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003514{
3515 struct alc_spec *spec = codec->spec;
Takashi Iwai8cd07752011-08-23 15:16:22 +02003516 int i;
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003517 hda_nid_t pin, dac;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003518
David Henningsson636030e2011-10-12 19:26:03 +02003519 for (i = 0; i < spec->autocfg.hp_outs; i++) {
Takashi Iwai716eef02011-10-21 15:07:42 +02003520 if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3521 break;
Takashi Iwaie23832a2011-08-23 18:16:56 +02003522 pin = spec->autocfg.hp_pins[i];
3523 if (!pin)
3524 break;
3525 dac = spec->multiout.hp_out_nid[i];
3526 if (!dac) {
3527 if (i > 0 && spec->multiout.hp_out_nid[0])
3528 dac = spec->multiout.hp_out_nid[0];
3529 else
3530 dac = spec->multiout.dac_nids[0];
3531 }
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003532 alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
3533 }
Takashi Iwai8cd07752011-08-23 15:16:22 +02003534 for (i = 0; i < spec->autocfg.speaker_outs; i++) {
Takashi Iwai716eef02011-10-21 15:07:42 +02003535 if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3536 break;
Takashi Iwai8cd07752011-08-23 15:16:22 +02003537 pin = spec->autocfg.speaker_pins[i];
3538 if (!pin)
3539 break;
3540 dac = spec->multiout.extra_out_nid[i];
3541 if (!dac) {
3542 if (i > 0 && spec->multiout.extra_out_nid[0])
3543 dac = spec->multiout.extra_out_nid[0];
3544 else
3545 dac = spec->multiout.dac_nids[0];
3546 }
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003547 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
3548 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003549}
3550
Takashi Iwaice764ab2011-04-27 16:35:23 +02003551/*
3552 * multi-io helper
3553 */
3554static int alc_auto_fill_multi_ios(struct hda_codec *codec,
Takashi Iwai07b18f62011-11-10 15:42:54 +01003555 unsigned int location,
3556 int offset)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003557{
3558 struct alc_spec *spec = codec->spec;
3559 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaic2674682011-08-24 17:57:44 +02003560 hda_nid_t prime_dac = spec->private_dac_nids[0];
Takashi Iwai07b18f62011-11-10 15:42:54 +01003561 int type, i, dacs, num_pins = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003562
Takashi Iwai07b18f62011-11-10 15:42:54 +01003563 dacs = spec->multiout.num_dacs;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003564 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3565 for (i = 0; i < cfg->num_inputs; i++) {
3566 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai07b18f62011-11-10 15:42:54 +01003567 hda_nid_t dac = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003568 unsigned int defcfg, caps;
3569 if (cfg->inputs[i].type != type)
3570 continue;
3571 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3572 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3573 continue;
3574 if (location && get_defcfg_location(defcfg) != location)
3575 continue;
3576 caps = snd_hda_query_pin_caps(codec, nid);
3577 if (!(caps & AC_PINCAP_OUT))
3578 continue;
Takashi Iwai07b18f62011-11-10 15:42:54 +01003579 if (offset && offset + num_pins < dacs) {
3580 dac = spec->private_dac_nids[offset + num_pins];
3581 if (!alc_auto_is_dac_reachable(codec, nid, dac))
3582 dac = 0;
3583 }
3584 if (!dac)
3585 dac = alc_auto_look_for_dac(codec, nid);
Takashi Iwaice764ab2011-04-27 16:35:23 +02003586 if (!dac)
3587 continue;
3588 spec->multi_io[num_pins].pin = nid;
3589 spec->multi_io[num_pins].dac = dac;
3590 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003591 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003592 }
3593 }
Takashi Iwai07b18f62011-11-10 15:42:54 +01003594 spec->multiout.num_dacs = dacs;
Takashi Iwaic2674682011-08-24 17:57:44 +02003595 if (num_pins < 2) {
3596 /* clear up again */
Takashi Iwai07b18f62011-11-10 15:42:54 +01003597 memset(spec->private_dac_nids + dacs, 0,
3598 sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs));
Takashi Iwaic2674682011-08-24 17:57:44 +02003599 spec->private_dac_nids[0] = prime_dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003600 return 0;
Takashi Iwaic2674682011-08-24 17:57:44 +02003601 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003602 return num_pins;
3603}
3604
3605static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3606 struct snd_ctl_elem_info *uinfo)
3607{
3608 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3609 struct alc_spec *spec = codec->spec;
3610
3611 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3612 uinfo->count = 1;
3613 uinfo->value.enumerated.items = spec->multi_ios + 1;
3614 if (uinfo->value.enumerated.item > spec->multi_ios)
3615 uinfo->value.enumerated.item = spec->multi_ios;
3616 sprintf(uinfo->value.enumerated.name, "%dch",
3617 (uinfo->value.enumerated.item + 1) * 2);
3618 return 0;
3619}
3620
3621static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3622 struct snd_ctl_elem_value *ucontrol)
3623{
3624 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3625 struct alc_spec *spec = codec->spec;
3626 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3627 return 0;
3628}
3629
3630static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3631{
3632 struct alc_spec *spec = codec->spec;
3633 hda_nid_t nid = spec->multi_io[idx].pin;
3634
3635 if (!spec->multi_io[idx].ctl_in)
3636 spec->multi_io[idx].ctl_in =
3637 snd_hda_codec_read(codec, nid, 0,
3638 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3639 if (output) {
3640 snd_hda_codec_update_cache(codec, nid, 0,
3641 AC_VERB_SET_PIN_WIDGET_CONTROL,
3642 PIN_OUT);
3643 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3644 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3645 HDA_AMP_MUTE, 0);
3646 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3647 } else {
3648 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3649 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3650 HDA_AMP_MUTE, HDA_AMP_MUTE);
3651 snd_hda_codec_update_cache(codec, nid, 0,
3652 AC_VERB_SET_PIN_WIDGET_CONTROL,
3653 spec->multi_io[idx].ctl_in);
3654 }
3655 return 0;
3656}
3657
3658static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3659 struct snd_ctl_elem_value *ucontrol)
3660{
3661 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3662 struct alc_spec *spec = codec->spec;
3663 int i, ch;
3664
3665 ch = ucontrol->value.enumerated.item[0];
3666 if (ch < 0 || ch > spec->multi_ios)
3667 return -EINVAL;
3668 if (ch == (spec->ext_channel_count - 1) / 2)
3669 return 0;
3670 spec->ext_channel_count = (ch + 1) * 2;
3671 for (i = 0; i < spec->multi_ios; i++)
3672 alc_set_multi_io(codec, i, i < ch);
3673 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003674 if (spec->need_dac_fix && !spec->const_channel_count)
3675 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003676 return 1;
3677}
3678
Takashi Iwaia9111322011-05-02 11:30:18 +02003679static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003680 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3681 .name = "Channel Mode",
3682 .info = alc_auto_ch_mode_info,
3683 .get = alc_auto_ch_mode_get,
3684 .put = alc_auto_ch_mode_put,
3685};
3686
Takashi Iwai23c09b02011-08-19 09:05:35 +02003687static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003688{
3689 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003690
Takashi Iwaic2674682011-08-24 17:57:44 +02003691 if (spec->multi_ios > 0) {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003692 struct snd_kcontrol_new *knew;
3693
3694 knew = alc_kcontrol_new(spec);
3695 if (!knew)
3696 return -ENOMEM;
3697 *knew = alc_auto_channel_mode_enum;
3698 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3699 if (!knew->name)
3700 return -ENOMEM;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003701 }
3702 return 0;
3703}
3704
Takashi Iwai1d045db2011-07-07 18:23:21 +02003705/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3706 * active input pins
3707 */
3708static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3709{
3710 struct alc_spec *spec = codec->spec;
3711 const struct hda_input_mux *imux;
3712 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3713 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3714 int i, n, nums;
3715
3716 imux = spec->input_mux;
3717 if (!imux)
3718 return;
3719 if (spec->dyn_adc_switch)
3720 return;
3721
3722 nums = 0;
3723 for (n = 0; n < spec->num_adc_nids; n++) {
3724 hda_nid_t cap = spec->private_capsrc_nids[n];
3725 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3726 for (i = 0; i < imux->num_items; i++) {
3727 hda_nid_t pin = spec->imux_pins[i];
3728 if (pin) {
3729 if (get_connection_index(codec, cap, pin) < 0)
3730 break;
3731 } else if (num_conns <= imux->items[i].index)
3732 break;
3733 }
3734 if (i >= imux->num_items) {
3735 adc_nids[nums] = spec->private_adc_nids[n];
3736 capsrc_nids[nums++] = cap;
3737 }
3738 }
3739 if (!nums) {
3740 /* check whether ADC-switch is possible */
3741 if (!alc_check_dyn_adc_switch(codec)) {
3742 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3743 " using fallback 0x%x\n",
3744 codec->chip_name, spec->private_adc_nids[0]);
3745 spec->num_adc_nids = 1;
3746 spec->auto_mic = 0;
3747 return;
3748 }
3749 } else if (nums != spec->num_adc_nids) {
3750 memcpy(spec->private_adc_nids, adc_nids,
3751 nums * sizeof(hda_nid_t));
3752 memcpy(spec->private_capsrc_nids, capsrc_nids,
3753 nums * sizeof(hda_nid_t));
3754 spec->num_adc_nids = nums;
3755 }
3756
3757 if (spec->auto_mic)
3758 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3759 else if (spec->input_mux->num_items == 1)
3760 spec->num_adc_nids = 1; /* reduce to a single ADC */
3761}
3762
3763/*
3764 * initialize ADC paths
3765 */
3766static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3767{
3768 struct alc_spec *spec = codec->spec;
3769 hda_nid_t nid;
3770
3771 nid = spec->adc_nids[adc_idx];
3772 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003773 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003774 snd_hda_codec_write(codec, nid, 0,
3775 AC_VERB_SET_AMP_GAIN_MUTE,
3776 AMP_IN_MUTE(0));
3777 return;
3778 }
3779 if (!spec->capsrc_nids)
3780 return;
3781 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003782 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003783 snd_hda_codec_write(codec, nid, 0,
3784 AC_VERB_SET_AMP_GAIN_MUTE,
3785 AMP_OUT_MUTE);
3786}
3787
3788static void alc_auto_init_input_src(struct hda_codec *codec)
3789{
3790 struct alc_spec *spec = codec->spec;
3791 int c, nums;
3792
3793 for (c = 0; c < spec->num_adc_nids; c++)
3794 alc_auto_init_adc(codec, c);
3795 if (spec->dyn_adc_switch)
3796 nums = 1;
3797 else
3798 nums = spec->num_adc_nids;
3799 for (c = 0; c < nums; c++)
3800 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3801}
3802
3803/* add mic boosts if needed */
3804static int alc_auto_add_mic_boost(struct hda_codec *codec)
3805{
3806 struct alc_spec *spec = codec->spec;
3807 struct auto_pin_cfg *cfg = &spec->autocfg;
3808 int i, err;
3809 int type_idx = 0;
3810 hda_nid_t nid;
3811 const char *prev_label = NULL;
3812
3813 for (i = 0; i < cfg->num_inputs; i++) {
3814 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3815 break;
3816 nid = cfg->inputs[i].pin;
3817 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3818 const char *label;
3819 char boost_label[32];
3820
3821 label = hda_get_autocfg_input_label(codec, cfg, i);
Takashi Iwai24de1832011-11-07 17:13:39 +01003822 if (spec->shared_mic_hp && !strcmp(label, "Misc"))
3823 label = "Headphone Mic";
Takashi Iwai1d045db2011-07-07 18:23:21 +02003824 if (prev_label && !strcmp(label, prev_label))
3825 type_idx++;
3826 else
3827 type_idx = 0;
3828 prev_label = label;
3829
3830 snprintf(boost_label, sizeof(boost_label),
3831 "%s Boost Volume", label);
3832 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3833 boost_label, type_idx,
3834 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3835 if (err < 0)
3836 return err;
3837 }
3838 }
3839 return 0;
3840}
3841
3842/* select or unmute the given capsrc route */
3843static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3844 int idx)
3845{
3846 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3847 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3848 HDA_AMP_MUTE, 0);
3849 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3850 snd_hda_codec_write_cache(codec, cap, 0,
3851 AC_VERB_SET_CONNECT_SEL, idx);
3852 }
3853}
3854
3855/* set the default connection to that pin */
3856static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3857{
3858 struct alc_spec *spec = codec->spec;
3859 int i;
3860
3861 if (!pin)
3862 return 0;
3863 for (i = 0; i < spec->num_adc_nids; i++) {
Takashi Iwai61071592011-11-23 07:52:15 +01003864 hda_nid_t cap = get_capsrc(spec, i);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003865 int idx;
3866
3867 idx = get_connection_index(codec, cap, pin);
3868 if (idx < 0)
3869 continue;
3870 select_or_unmute_capsrc(codec, cap, idx);
3871 return i; /* return the found index */
3872 }
3873 return -1; /* not found */
3874}
3875
3876/* initialize some special cases for input sources */
3877static void alc_init_special_input_src(struct hda_codec *codec)
3878{
3879 struct alc_spec *spec = codec->spec;
3880 int i;
3881
3882 for (i = 0; i < spec->autocfg.num_inputs; i++)
3883 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3884}
3885
3886/* assign appropriate capture mixers */
3887static void set_capture_mixer(struct hda_codec *codec)
3888{
3889 struct alc_spec *spec = codec->spec;
3890 static const struct snd_kcontrol_new *caps[2][3] = {
3891 { alc_capture_mixer_nosrc1,
3892 alc_capture_mixer_nosrc2,
3893 alc_capture_mixer_nosrc3 },
3894 { alc_capture_mixer1,
3895 alc_capture_mixer2,
3896 alc_capture_mixer3 },
3897 };
3898
3899 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003900 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003901 if (!spec->capsrc_nids)
3902 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003903 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003904 return; /* no volume in capsrc, too */
3905 spec->vol_in_capsrc = 1;
3906 }
3907
3908 if (spec->num_adc_nids > 0) {
3909 int mux = 0;
3910 int num_adcs = 0;
3911
3912 if (spec->input_mux && spec->input_mux->num_items > 1)
3913 mux = 1;
3914 if (spec->auto_mic) {
3915 num_adcs = 1;
3916 mux = 0;
3917 } else if (spec->dyn_adc_switch)
3918 num_adcs = 1;
3919 if (!num_adcs) {
3920 if (spec->num_adc_nids > 3)
3921 spec->num_adc_nids = 3;
3922 else if (!spec->num_adc_nids)
3923 return;
3924 num_adcs = spec->num_adc_nids;
3925 }
3926 spec->cap_mixer = caps[mux][num_adcs - 1];
3927 }
3928}
3929
3930/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003931 * standard auto-parser initializations
3932 */
3933static void alc_auto_init_std(struct hda_codec *codec)
3934{
3935 struct alc_spec *spec = codec->spec;
3936 alc_auto_init_multi_out(codec);
3937 alc_auto_init_extra_out(codec);
3938 alc_auto_init_analog_input(codec);
3939 alc_auto_init_input_src(codec);
3940 alc_auto_init_digital(codec);
3941 if (spec->unsol_event)
3942 alc_inithook(codec);
3943}
3944
3945/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003946 * Digital-beep handlers
3947 */
3948#ifdef CONFIG_SND_HDA_INPUT_BEEP
3949#define set_beep_amp(spec, nid, idx, dir) \
3950 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3951
3952static const struct snd_pci_quirk beep_white_list[] = {
3953 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3954 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3955 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3956 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3957 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3958 {}
3959};
3960
3961static inline int has_cdefine_beep(struct hda_codec *codec)
3962{
3963 struct alc_spec *spec = codec->spec;
3964 const struct snd_pci_quirk *q;
3965 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3966 if (q)
3967 return q->value;
3968 return spec->cdefine.enable_pcbeep;
3969}
3970#else
3971#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3972#define has_cdefine_beep(codec) 0
3973#endif
3974
3975/* parse the BIOS configuration and set up the alc_spec */
3976/* return 1 if successful, 0 if the proper config is not found,
3977 * or a negative error code
3978 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003979static int alc_parse_auto_config(struct hda_codec *codec,
3980 const hda_nid_t *ignore_nids,
3981 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003982{
3983 struct alc_spec *spec = codec->spec;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003984 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003985 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003986
Takashi Iwai53c334a2011-08-23 18:27:14 +02003987 err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
3988 spec->parse_flags);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003989 if (err < 0)
3990 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003991 if (!cfg->line_outs) {
3992 if (cfg->dig_outs || cfg->dig_in_pin) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003993 spec->multiout.max_channels = 2;
3994 spec->no_analog = 1;
3995 goto dig_only;
3996 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003997 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003998 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02003999
Takashi Iwai06503672011-10-06 08:27:19 +02004000 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4001 cfg->line_outs <= cfg->hp_outs) {
Takashi Iwai23c09b02011-08-19 09:05:35 +02004002 /* use HP as primary out */
4003 cfg->speaker_outs = cfg->line_outs;
4004 memcpy(cfg->speaker_pins, cfg->line_out_pins,
4005 sizeof(cfg->speaker_pins));
4006 cfg->line_outs = cfg->hp_outs;
4007 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4008 cfg->hp_outs = 0;
4009 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4010 cfg->line_out_type = AUTO_PIN_HP_OUT;
4011 }
4012
Takashi Iwai1d045db2011-07-07 18:23:21 +02004013 err = alc_auto_fill_dac_nids(codec);
4014 if (err < 0)
4015 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02004016 err = alc_auto_add_multi_channel_mode(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004017 if (err < 0)
4018 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02004019 err = alc_auto_create_multi_out_ctls(codec, cfg);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004020 if (err < 0)
4021 return err;
4022 err = alc_auto_create_hp_out(codec);
4023 if (err < 0)
4024 return err;
4025 err = alc_auto_create_speaker_out(codec);
4026 if (err < 0)
4027 return err;
Takashi Iwai24de1832011-11-07 17:13:39 +01004028 err = alc_auto_create_shared_input(codec);
4029 if (err < 0)
4030 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004031 err = alc_auto_create_input_ctls(codec);
4032 if (err < 0)
4033 return err;
4034
4035 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4036
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004037 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02004038 alc_auto_parse_digital(codec);
4039
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004040 if (!spec->no_analog)
4041 alc_remove_invalid_adc_nids(codec);
4042
4043 if (ssid_nids)
4044 alc_ssid_check(codec, ssid_nids);
4045
4046 if (!spec->no_analog) {
4047 alc_auto_check_switches(codec);
4048 err = alc_auto_add_mic_boost(codec);
4049 if (err < 0)
4050 return err;
4051 }
4052
Takashi Iwai1d045db2011-07-07 18:23:21 +02004053 if (spec->kctls.list)
4054 add_mixer(spec, spec->kctls.list);
4055
Takashi Iwai1d045db2011-07-07 18:23:21 +02004056 return 1;
4057}
4058
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004059static int alc880_parse_auto_config(struct hda_codec *codec)
4060{
4061 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
4062 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4063 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
4064}
4065
Takashi Iwai1d045db2011-07-07 18:23:21 +02004066#ifdef CONFIG_SND_HDA_POWER_SAVE
4067static const struct hda_amp_list alc880_loopbacks[] = {
4068 { 0x0b, HDA_INPUT, 0 },
4069 { 0x0b, HDA_INPUT, 1 },
4070 { 0x0b, HDA_INPUT, 2 },
4071 { 0x0b, HDA_INPUT, 3 },
4072 { 0x0b, HDA_INPUT, 4 },
4073 { } /* end */
4074};
4075#endif
4076
4077/*
Takashi Iwaiee3b2962011-11-15 14:26:54 +01004078 * ALC880 fix-ups
4079 */
4080enum {
4081 ALC880_FIXUP_GPIO2,
4082 ALC880_FIXUP_MEDION_RIM,
4083};
4084
4085static const struct alc_fixup alc880_fixups[] = {
4086 [ALC880_FIXUP_GPIO2] = {
4087 .type = ALC_FIXUP_VERBS,
4088 .v.verbs = alc_gpio2_init_verbs,
4089 },
4090 [ALC880_FIXUP_MEDION_RIM] = {
4091 .type = ALC_FIXUP_VERBS,
4092 .v.verbs = (const struct hda_verb[]) {
4093 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
4094 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
4095 { }
4096 },
4097 .chained = true,
4098 .chain_id = ALC880_FIXUP_GPIO2,
4099 },
4100};
4101
4102static const struct snd_pci_quirk alc880_fixup_tbl[] = {
4103 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
4104 {}
4105};
4106
4107
4108/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02004109 * board setups
4110 */
4111#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4112#define alc_board_config \
4113 snd_hda_check_board_config
4114#define alc_board_codec_sid_config \
4115 snd_hda_check_board_codec_sid_config
4116#include "alc_quirks.c"
4117#else
4118#define alc_board_config(codec, nums, models, tbl) -1
4119#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
4120#define setup_preset(codec, x) /* NOP */
4121#endif
4122
4123/*
4124 * OK, here we have finally the patch for ALC880
4125 */
4126#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4127#include "alc880_quirks.c"
4128#endif
4129
4130static int patch_alc880(struct hda_codec *codec)
4131{
4132 struct alc_spec *spec;
4133 int board_config;
4134 int err;
4135
4136 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4137 if (spec == NULL)
4138 return -ENOMEM;
4139
4140 codec->spec = spec;
4141
4142 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02004143 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004144
4145 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
4146 alc880_models, alc880_cfg_tbl);
4147 if (board_config < 0) {
4148 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4149 codec->chip_name);
4150 board_config = ALC_MODEL_AUTO;
4151 }
4152
4153 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaiee3b2962011-11-15 14:26:54 +01004154 alc_pick_fixup(codec, NULL, alc880_fixup_tbl, alc880_fixups);
4155 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4156 }
4157
4158 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004159 /* automatic parse from the BIOS config */
4160 err = alc880_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004161 if (err < 0)
4162 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004163#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4164 else if (!err) {
4165 printk(KERN_INFO
4166 "hda_codec: Cannot set up configuration "
4167 "from BIOS. Using 3-stack mode...\n");
4168 board_config = ALC880_3ST;
4169 }
4170#endif
4171 }
4172
David Henningssonfde48a12011-12-09 18:27:42 +08004173 if (board_config != ALC_MODEL_AUTO) {
4174 spec->vmaster_nid = 0x0c;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004175 setup_preset(codec, &alc880_presets[board_config]);
David Henningssonfde48a12011-12-09 18:27:42 +08004176 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004177
Takashi Iwai60a6a842011-07-27 14:01:24 +02004178 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004179 alc_auto_fill_adc_caps(codec);
4180 alc_rebuild_imux_for_auto_mic(codec);
4181 alc_remove_invalid_adc_nids(codec);
4182 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004183
4184 if (!spec->no_analog && !spec->cap_mixer)
4185 set_capture_mixer(codec);
4186
4187 if (!spec->no_analog) {
4188 err = snd_hda_attach_beep_device(codec, 0x1);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004189 if (err < 0)
4190 goto error;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004191 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
4192 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004193
Takashi Iwaiee3b2962011-11-15 14:26:54 +01004194 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4195
Takashi Iwai1d045db2011-07-07 18:23:21 +02004196 codec->patch_ops = alc_patch_ops;
4197 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004198 spec->init_hook = alc_auto_init_std;
Takashi Iwaif21d78e2012-01-19 12:10:29 +01004199 else
4200 codec->patch_ops.build_controls = __alc_build_controls;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004201#ifdef CONFIG_SND_HDA_POWER_SAVE
4202 if (!spec->loopback.amplist)
4203 spec->loopback.amplist = alc880_loopbacks;
4204#endif
4205
4206 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004207
4208 error:
4209 alc_free(codec);
4210 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004211}
4212
4213
4214/*
4215 * ALC260 support
4216 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004217static int alc260_parse_auto_config(struct hda_codec *codec)
4218{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004219 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004220 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
4221 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004222}
4223
Takashi Iwai1d045db2011-07-07 18:23:21 +02004224#ifdef CONFIG_SND_HDA_POWER_SAVE
4225static const struct hda_amp_list alc260_loopbacks[] = {
4226 { 0x07, HDA_INPUT, 0 },
4227 { 0x07, HDA_INPUT, 1 },
4228 { 0x07, HDA_INPUT, 2 },
4229 { 0x07, HDA_INPUT, 3 },
4230 { 0x07, HDA_INPUT, 4 },
4231 { } /* end */
4232};
4233#endif
4234
4235/*
4236 * Pin config fixes
4237 */
4238enum {
4239 PINFIX_HP_DC5750,
4240};
4241
4242static const struct alc_fixup alc260_fixups[] = {
4243 [PINFIX_HP_DC5750] = {
4244 .type = ALC_FIXUP_PINS,
4245 .v.pins = (const struct alc_pincfg[]) {
4246 { 0x11, 0x90130110 }, /* speaker */
4247 { }
4248 }
4249 },
4250};
4251
4252static const struct snd_pci_quirk alc260_fixup_tbl[] = {
4253 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
4254 {}
4255};
4256
4257/*
4258 */
4259#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4260#include "alc260_quirks.c"
4261#endif
4262
4263static int patch_alc260(struct hda_codec *codec)
4264{
4265 struct alc_spec *spec;
4266 int err, board_config;
4267
4268 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4269 if (spec == NULL)
4270 return -ENOMEM;
4271
4272 codec->spec = spec;
4273
4274 spec->mixer_nid = 0x07;
4275
4276 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
4277 alc260_models, alc260_cfg_tbl);
4278 if (board_config < 0) {
4279 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4280 codec->chip_name);
4281 board_config = ALC_MODEL_AUTO;
4282 }
4283
4284 if (board_config == ALC_MODEL_AUTO) {
4285 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
4286 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4287 }
4288
4289 if (board_config == ALC_MODEL_AUTO) {
4290 /* automatic parse from the BIOS config */
4291 err = alc260_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004292 if (err < 0)
4293 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004294#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4295 else if (!err) {
4296 printk(KERN_INFO
4297 "hda_codec: Cannot set up configuration "
4298 "from BIOS. Using base mode...\n");
4299 board_config = ALC260_BASIC;
4300 }
4301#endif
4302 }
4303
David Henningssonfde48a12011-12-09 18:27:42 +08004304 if (board_config != ALC_MODEL_AUTO) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004305 setup_preset(codec, &alc260_presets[board_config]);
David Henningssonfde48a12011-12-09 18:27:42 +08004306 spec->vmaster_nid = 0x08;
4307 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004308
Takashi Iwai60a6a842011-07-27 14:01:24 +02004309 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004310 alc_auto_fill_adc_caps(codec);
4311 alc_rebuild_imux_for_auto_mic(codec);
4312 alc_remove_invalid_adc_nids(codec);
4313 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004314
4315 if (!spec->no_analog && !spec->cap_mixer)
4316 set_capture_mixer(codec);
4317
4318 if (!spec->no_analog) {
4319 err = snd_hda_attach_beep_device(codec, 0x1);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004320 if (err < 0)
4321 goto error;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004322 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
4323 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004324
4325 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4326
Takashi Iwai1d045db2011-07-07 18:23:21 +02004327 codec->patch_ops = alc_patch_ops;
4328 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02004329 spec->init_hook = alc_auto_init_std;
Takashi Iwaif21d78e2012-01-19 12:10:29 +01004330 else
4331 codec->patch_ops.build_controls = __alc_build_controls;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004332 spec->shutup = alc_eapd_shutup;
4333#ifdef CONFIG_SND_HDA_POWER_SAVE
4334 if (!spec->loopback.amplist)
4335 spec->loopback.amplist = alc260_loopbacks;
4336#endif
4337
4338 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004339
4340 error:
4341 alc_free(codec);
4342 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004343}
4344
4345
4346/*
4347 * ALC882/883/885/888/889 support
4348 *
4349 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
4350 * configuration. Each pin widget can choose any input DACs and a mixer.
4351 * Each ADC is connected from a mixer of all inputs. This makes possible
4352 * 6-channel independent captures.
4353 *
4354 * In addition, an independent DAC for the multi-playback (not used in this
4355 * driver yet).
4356 */
4357#ifdef CONFIG_SND_HDA_POWER_SAVE
4358#define alc882_loopbacks alc880_loopbacks
4359#endif
4360
4361/*
4362 * Pin config fixes
4363 */
4364enum {
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004365 ALC882_FIXUP_ABIT_AW9D_MAX,
4366 ALC882_FIXUP_LENOVO_Y530,
4367 ALC882_FIXUP_PB_M5210,
4368 ALC882_FIXUP_ACER_ASPIRE_7736,
4369 ALC882_FIXUP_ASUS_W90V,
4370 ALC889_FIXUP_VAIO_TT,
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01004371 ALC888_FIXUP_EEE1601,
Takashi Iwai177943a2011-11-09 12:55:18 +01004372 ALC882_FIXUP_EAPD,
Takashi Iwai7a6069b2011-11-09 15:22:01 +01004373 ALC883_FIXUP_EAPD,
Takashi Iwai8812c4f2011-11-09 17:39:15 +01004374 ALC883_FIXUP_ACER_EAPD,
Takashi Iwaieb844d52011-11-09 18:03:07 +01004375 ALC882_FIXUP_GPIO3,
Takashi Iwai68ef0562011-11-09 18:24:44 +01004376 ALC889_FIXUP_COEF,
4377 ALC882_FIXUP_ASUS_W2JC,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01004378 ALC882_FIXUP_ACER_ASPIRE_4930G,
4379 ALC882_FIXUP_ACER_ASPIRE_8930G,
4380 ALC882_FIXUP_ASPIRE_8930G_VERBS,
Takashi Iwai56710872011-11-14 17:42:11 +01004381 ALC885_FIXUP_MACPRO_GPIO,
Takashi Iwai02a237b2012-02-13 15:25:07 +01004382 ALC889_FIXUP_DAC_ROUTE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004383};
4384
Takashi Iwai68ef0562011-11-09 18:24:44 +01004385static void alc889_fixup_coef(struct hda_codec *codec,
4386 const struct alc_fixup *fix, int action)
4387{
4388 if (action != ALC_FIXUP_ACT_INIT)
4389 return;
4390 alc889_coef_init(codec);
4391}
4392
Takashi Iwai56710872011-11-14 17:42:11 +01004393/* toggle speaker-output according to the hp-jack state */
4394static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
4395{
4396 unsigned int gpiostate, gpiomask, gpiodir;
4397
4398 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
4399 AC_VERB_GET_GPIO_DATA, 0);
4400
4401 if (!muted)
4402 gpiostate |= (1 << pin);
4403 else
4404 gpiostate &= ~(1 << pin);
4405
4406 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
4407 AC_VERB_GET_GPIO_MASK, 0);
4408 gpiomask |= (1 << pin);
4409
4410 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
4411 AC_VERB_GET_GPIO_DIRECTION, 0);
4412 gpiodir |= (1 << pin);
4413
4414
4415 snd_hda_codec_write(codec, codec->afg, 0,
4416 AC_VERB_SET_GPIO_MASK, gpiomask);
4417 snd_hda_codec_write(codec, codec->afg, 0,
4418 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
4419
4420 msleep(1);
4421
4422 snd_hda_codec_write(codec, codec->afg, 0,
4423 AC_VERB_SET_GPIO_DATA, gpiostate);
4424}
4425
4426/* set up GPIO at initialization */
4427static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
4428 const struct alc_fixup *fix, int action)
4429{
4430 if (action != ALC_FIXUP_ACT_INIT)
4431 return;
4432 alc882_gpio_mute(codec, 0, 0);
4433 alc882_gpio_mute(codec, 1, 0);
4434}
4435
Takashi Iwai02a237b2012-02-13 15:25:07 +01004436/* Fix the connection of some pins for ALC889:
4437 * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
4438 * work correctly (bko#42740)
4439 */
4440static void alc889_fixup_dac_route(struct hda_codec *codec,
4441 const struct alc_fixup *fix, int action)
4442{
4443 if (action == ALC_FIXUP_ACT_PRE_PROBE) {
Takashi Iwaief8d60f2012-02-17 10:12:38 +01004444 /* fake the connections during parsing the tree */
Takashi Iwai02a237b2012-02-13 15:25:07 +01004445 hda_nid_t conn1[2] = { 0x0c, 0x0d };
4446 hda_nid_t conn2[2] = { 0x0e, 0x0f };
4447 snd_hda_override_conn_list(codec, 0x14, 2, conn1);
4448 snd_hda_override_conn_list(codec, 0x15, 2, conn1);
4449 snd_hda_override_conn_list(codec, 0x18, 2, conn2);
4450 snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
Takashi Iwaief8d60f2012-02-17 10:12:38 +01004451 } else if (action == ALC_FIXUP_ACT_PROBE) {
4452 /* restore the connections */
4453 hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
4454 snd_hda_override_conn_list(codec, 0x14, 5, conn);
4455 snd_hda_override_conn_list(codec, 0x15, 5, conn);
4456 snd_hda_override_conn_list(codec, 0x18, 5, conn);
4457 snd_hda_override_conn_list(codec, 0x1a, 5, conn);
Takashi Iwai02a237b2012-02-13 15:25:07 +01004458 }
4459}
4460
Takashi Iwai1d045db2011-07-07 18:23:21 +02004461static const struct alc_fixup alc882_fixups[] = {
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004462 [ALC882_FIXUP_ABIT_AW9D_MAX] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004463 .type = ALC_FIXUP_PINS,
4464 .v.pins = (const struct alc_pincfg[]) {
4465 { 0x15, 0x01080104 }, /* side */
4466 { 0x16, 0x01011012 }, /* rear */
4467 { 0x17, 0x01016011 }, /* clfe */
4468 { }
4469 }
4470 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004471 [ALC882_FIXUP_LENOVO_Y530] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004472 .type = ALC_FIXUP_PINS,
4473 .v.pins = (const struct alc_pincfg[]) {
4474 { 0x15, 0x99130112 }, /* rear int speakers */
4475 { 0x16, 0x99130111 }, /* subwoofer */
4476 { }
4477 }
4478 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004479 [ALC882_FIXUP_PB_M5210] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004480 .type = ALC_FIXUP_VERBS,
4481 .v.verbs = (const struct hda_verb[]) {
4482 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
4483 {}
4484 }
4485 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004486 [ALC882_FIXUP_ACER_ASPIRE_7736] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004487 .type = ALC_FIXUP_SKU,
4488 .v.sku = ALC_FIXUP_SKU_IGNORE,
4489 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004490 [ALC882_FIXUP_ASUS_W90V] = {
Takashi Iwai5cdf7452011-10-26 23:04:08 +02004491 .type = ALC_FIXUP_PINS,
4492 .v.pins = (const struct alc_pincfg[]) {
4493 { 0x16, 0x99130110 }, /* fix sequence for CLFE */
4494 { }
4495 }
4496 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004497 [ALC889_FIXUP_VAIO_TT] = {
4498 .type = ALC_FIXUP_PINS,
4499 .v.pins = (const struct alc_pincfg[]) {
4500 { 0x17, 0x90170111 }, /* hidden surround speaker */
4501 { }
4502 }
4503 },
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01004504 [ALC888_FIXUP_EEE1601] = {
4505 .type = ALC_FIXUP_VERBS,
4506 .v.verbs = (const struct hda_verb[]) {
4507 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
4508 { 0x20, AC_VERB_SET_PROC_COEF, 0x0838 },
4509 { }
4510 }
Takashi Iwai177943a2011-11-09 12:55:18 +01004511 },
4512 [ALC882_FIXUP_EAPD] = {
4513 .type = ALC_FIXUP_VERBS,
4514 .v.verbs = (const struct hda_verb[]) {
4515 /* change to EAPD mode */
4516 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
4517 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
4518 { }
4519 }
4520 },
Takashi Iwai7a6069b2011-11-09 15:22:01 +01004521 [ALC883_FIXUP_EAPD] = {
4522 .type = ALC_FIXUP_VERBS,
4523 .v.verbs = (const struct hda_verb[]) {
4524 /* change to EAPD mode */
4525 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
4526 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
4527 { }
4528 }
4529 },
Takashi Iwai8812c4f2011-11-09 17:39:15 +01004530 [ALC883_FIXUP_ACER_EAPD] = {
4531 .type = ALC_FIXUP_VERBS,
4532 .v.verbs = (const struct hda_verb[]) {
4533 /* eanable EAPD on Acer laptops */
4534 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
4535 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
4536 { }
4537 }
4538 },
Takashi Iwaieb844d52011-11-09 18:03:07 +01004539 [ALC882_FIXUP_GPIO3] = {
4540 .type = ALC_FIXUP_VERBS,
4541 .v.verbs = alc_gpio3_init_verbs,
4542 },
Takashi Iwai68ef0562011-11-09 18:24:44 +01004543 [ALC882_FIXUP_ASUS_W2JC] = {
4544 .type = ALC_FIXUP_VERBS,
4545 .v.verbs = alc_gpio1_init_verbs,
4546 .chained = true,
4547 .chain_id = ALC882_FIXUP_EAPD,
4548 },
4549 [ALC889_FIXUP_COEF] = {
4550 .type = ALC_FIXUP_FUNC,
4551 .v.func = alc889_fixup_coef,
4552 },
Takashi Iwaic3e837b2011-11-10 16:01:47 +01004553 [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
4554 .type = ALC_FIXUP_PINS,
4555 .v.pins = (const struct alc_pincfg[]) {
4556 { 0x16, 0x99130111 }, /* CLFE speaker */
4557 { 0x17, 0x99130112 }, /* surround speaker */
4558 { }
4559 }
4560 },
4561 [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
4562 .type = ALC_FIXUP_PINS,
4563 .v.pins = (const struct alc_pincfg[]) {
4564 { 0x16, 0x99130111 }, /* CLFE speaker */
4565 { 0x1b, 0x99130112 }, /* surround speaker */
4566 { }
4567 },
4568 .chained = true,
4569 .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
4570 },
4571 [ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
4572 /* additional init verbs for Acer Aspire 8930G */
4573 .type = ALC_FIXUP_VERBS,
4574 .v.verbs = (const struct hda_verb[]) {
4575 /* Enable all DACs */
4576 /* DAC DISABLE/MUTE 1? */
4577 /* setting bits 1-5 disables DAC nids 0x02-0x06
4578 * apparently. Init=0x38 */
4579 { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
4580 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
4581 /* DAC DISABLE/MUTE 2? */
4582 /* some bit here disables the other DACs.
4583 * Init=0x4900 */
4584 { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
4585 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
4586 /* DMIC fix
4587 * This laptop has a stereo digital microphone.
4588 * The mics are only 1cm apart which makes the stereo
4589 * useless. However, either the mic or the ALC889
4590 * makes the signal become a difference/sum signal
4591 * instead of standard stereo, which is annoying.
4592 * So instead we flip this bit which makes the
4593 * codec replicate the sum signal to both channels,
4594 * turning it into a normal mono mic.
4595 */
4596 /* DMIC_CONTROL? Init value = 0x0001 */
4597 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
4598 { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
4599 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
4600 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
4601 { }
4602 }
4603 },
Takashi Iwai56710872011-11-14 17:42:11 +01004604 [ALC885_FIXUP_MACPRO_GPIO] = {
4605 .type = ALC_FIXUP_FUNC,
4606 .v.func = alc885_fixup_macpro_gpio,
4607 },
Takashi Iwai02a237b2012-02-13 15:25:07 +01004608 [ALC889_FIXUP_DAC_ROUTE] = {
4609 .type = ALC_FIXUP_FUNC,
4610 .v.func = alc889_fixup_dac_route,
4611 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004612};
4613
4614static const struct snd_pci_quirk alc882_fixup_tbl[] = {
Takashi Iwai8812c4f2011-11-09 17:39:15 +01004615 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
4616 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
4617 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
4618 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
4619 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
4620 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
Takashi Iwaic3e837b2011-11-10 16:01:47 +01004621 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
4622 ALC882_FIXUP_ACER_ASPIRE_4930G),
4623 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
4624 ALC882_FIXUP_ACER_ASPIRE_4930G),
4625 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
4626 ALC882_FIXUP_ACER_ASPIRE_8930G),
4627 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
4628 ALC882_FIXUP_ACER_ASPIRE_8930G),
4629 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
4630 ALC882_FIXUP_ACER_ASPIRE_4930G),
4631 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
4632 ALC882_FIXUP_ACER_ASPIRE_4930G),
4633 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
4634 ALC882_FIXUP_ACER_ASPIRE_4930G),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004635 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
Takashi Iwai02a237b2012-02-13 15:25:07 +01004636 SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01004637 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
Takashi Iwai177943a2011-11-09 12:55:18 +01004638 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004639 SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
Takashi Iwai68ef0562011-11-09 18:24:44 +01004640 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01004641 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01004642 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
Takashi Iwai56710872011-11-14 17:42:11 +01004643
4644 /* All Apple entries are in codec SSIDs */
4645 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
4646 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
4647 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
4648 SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
4649 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
4650
Takashi Iwai7a6069b2011-11-09 15:22:01 +01004651 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
Takashi Iwaieb844d52011-11-09 18:03:07 +01004652 SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01004653 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
Takashi Iwai7a6069b2011-11-09 15:22:01 +01004654 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
4655 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01004656 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
Takashi Iwai68ef0562011-11-09 18:24:44 +01004657 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004658 {}
4659};
4660
4661/*
4662 * BIOS auto configuration
4663 */
4664/* almost identical with ALC880 parser... */
4665static int alc882_parse_auto_config(struct hda_codec *codec)
4666{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004667 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004668 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4669 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004670}
4671
Takashi Iwai1d045db2011-07-07 18:23:21 +02004672/*
4673 */
4674#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4675#include "alc882_quirks.c"
4676#endif
4677
4678static int patch_alc882(struct hda_codec *codec)
4679{
4680 struct alc_spec *spec;
4681 int err, board_config;
4682
4683 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4684 if (spec == NULL)
4685 return -ENOMEM;
4686
4687 codec->spec = spec;
4688
4689 spec->mixer_nid = 0x0b;
4690
4691 switch (codec->vendor_id) {
4692 case 0x10ec0882:
4693 case 0x10ec0885:
4694 break;
4695 default:
4696 /* ALC883 and variants */
4697 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4698 break;
4699 }
4700
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004701 err = alc_codec_rename_from_preset(codec);
4702 if (err < 0)
4703 goto error;
4704
Takashi Iwaib2539692011-11-14 17:32:17 +01004705 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
4706 alc882_models, NULL);
4707 if (board_config < 0)
4708 board_config = alc_board_codec_sid_config(codec,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004709 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
4710
4711 if (board_config < 0) {
4712 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4713 codec->chip_name);
4714 board_config = ALC_MODEL_AUTO;
4715 }
4716
4717 if (board_config == ALC_MODEL_AUTO) {
4718 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
4719 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4720 }
4721
4722 alc_auto_parse_customize_define(codec);
4723
4724 if (board_config == ALC_MODEL_AUTO) {
4725 /* automatic parse from the BIOS config */
4726 err = alc882_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004727 if (err < 0)
4728 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004729 }
4730
David Henningssonfde48a12011-12-09 18:27:42 +08004731 if (board_config != ALC_MODEL_AUTO) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004732 setup_preset(codec, &alc882_presets[board_config]);
David Henningssonfde48a12011-12-09 18:27:42 +08004733 spec->vmaster_nid = 0x0c;
4734 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004735
Takashi Iwai60a6a842011-07-27 14:01:24 +02004736 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004737 alc_auto_fill_adc_caps(codec);
4738 alc_rebuild_imux_for_auto_mic(codec);
4739 alc_remove_invalid_adc_nids(codec);
4740 }
4741
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004742 if (!spec->no_analog && !spec->cap_mixer)
4743 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004744
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004745 if (!spec->no_analog && has_cdefine_beep(codec)) {
4746 err = snd_hda_attach_beep_device(codec, 0x1);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004747 if (err < 0)
4748 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004749 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004750 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004751
4752 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4753
Takashi Iwai1d045db2011-07-07 18:23:21 +02004754 codec->patch_ops = alc_patch_ops;
4755 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004756 spec->init_hook = alc_auto_init_std;
Takashi Iwaif21d78e2012-01-19 12:10:29 +01004757 else
4758 codec->patch_ops.build_controls = __alc_build_controls;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004759
Takashi Iwai1d045db2011-07-07 18:23:21 +02004760#ifdef CONFIG_SND_HDA_POWER_SAVE
4761 if (!spec->loopback.amplist)
4762 spec->loopback.amplist = alc882_loopbacks;
4763#endif
4764
4765 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004766
4767 error:
4768 alc_free(codec);
4769 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004770}
4771
4772
4773/*
4774 * ALC262 support
4775 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004776static int alc262_parse_auto_config(struct hda_codec *codec)
4777{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004778 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004779 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4780 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004781}
4782
4783/*
4784 * Pin config fixes
4785 */
4786enum {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01004787 ALC262_FIXUP_FSC_H270,
4788 ALC262_FIXUP_HP_Z200,
4789 ALC262_FIXUP_TYAN,
Takashi Iwaic4701502011-11-07 14:20:07 +01004790 ALC262_FIXUP_LENOVO_3000,
Takashi Iwaib42590b2011-11-07 14:41:01 +01004791 ALC262_FIXUP_BENQ,
4792 ALC262_FIXUP_BENQ_T31,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004793};
4794
4795static const struct alc_fixup alc262_fixups[] = {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01004796 [ALC262_FIXUP_FSC_H270] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004797 .type = ALC_FIXUP_PINS,
4798 .v.pins = (const struct alc_pincfg[]) {
4799 { 0x14, 0x99130110 }, /* speaker */
4800 { 0x15, 0x0221142f }, /* front HP */
4801 { 0x1b, 0x0121141f }, /* rear HP */
4802 { }
4803 }
4804 },
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01004805 [ALC262_FIXUP_HP_Z200] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004806 .type = ALC_FIXUP_PINS,
4807 .v.pins = (const struct alc_pincfg[]) {
4808 { 0x16, 0x99130120 }, /* internal speaker */
4809 { }
4810 }
4811 },
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01004812 [ALC262_FIXUP_TYAN] = {
4813 .type = ALC_FIXUP_PINS,
4814 .v.pins = (const struct alc_pincfg[]) {
4815 { 0x14, 0x1993e1f0 }, /* int AUX */
4816 { }
4817 }
4818 },
Takashi Iwaic4701502011-11-07 14:20:07 +01004819 [ALC262_FIXUP_LENOVO_3000] = {
4820 .type = ALC_FIXUP_VERBS,
4821 .v.verbs = (const struct hda_verb[]) {
4822 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
Takashi Iwaib42590b2011-11-07 14:41:01 +01004823 {}
4824 },
4825 .chained = true,
4826 .chain_id = ALC262_FIXUP_BENQ,
4827 },
4828 [ALC262_FIXUP_BENQ] = {
4829 .type = ALC_FIXUP_VERBS,
4830 .v.verbs = (const struct hda_verb[]) {
Takashi Iwaic4701502011-11-07 14:20:07 +01004831 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
4832 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
4833 {}
4834 }
4835 },
Takashi Iwaib42590b2011-11-07 14:41:01 +01004836 [ALC262_FIXUP_BENQ_T31] = {
4837 .type = ALC_FIXUP_VERBS,
4838 .v.verbs = (const struct hda_verb[]) {
4839 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
4840 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
4841 {}
4842 }
4843 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004844};
4845
4846static const struct snd_pci_quirk alc262_fixup_tbl[] = {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01004847 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
Takashi Iwai3dcd3be2011-11-07 14:59:40 +01004848 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ),
4849 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01004850 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
4851 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
Takashi Iwaic4701502011-11-07 14:20:07 +01004852 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
Takashi Iwaib42590b2011-11-07 14:41:01 +01004853 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
4854 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004855 {}
4856};
4857
4858
4859#ifdef CONFIG_SND_HDA_POWER_SAVE
4860#define alc262_loopbacks alc880_loopbacks
4861#endif
4862
Takashi Iwai1d045db2011-07-07 18:23:21 +02004863/*
4864 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004865static int patch_alc262(struct hda_codec *codec)
4866{
4867 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004868 int err;
4869
4870 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4871 if (spec == NULL)
4872 return -ENOMEM;
4873
4874 codec->spec = spec;
4875
4876 spec->mixer_nid = 0x0b;
4877
4878#if 0
4879 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4880 * under-run
4881 */
4882 {
4883 int tmp;
4884 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4885 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4886 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4887 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4888 }
4889#endif
4890 alc_auto_parse_customize_define(codec);
4891
4892 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4893
Takashi Iwai42399f72011-11-07 17:18:44 +01004894 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4895 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004896
Takashi Iwai42399f72011-11-07 17:18:44 +01004897 /* automatic parse from the BIOS config */
4898 err = alc262_parse_auto_config(codec);
4899 if (err < 0)
4900 goto error;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004901
Takashi Iwai60a6a842011-07-27 14:01:24 +02004902 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004903 alc_auto_fill_adc_caps(codec);
4904 alc_rebuild_imux_for_auto_mic(codec);
4905 alc_remove_invalid_adc_nids(codec);
4906 }
4907
4908 if (!spec->no_analog && !spec->cap_mixer)
4909 set_capture_mixer(codec);
4910
Takashi Iwai1d045db2011-07-07 18:23:21 +02004911 if (!spec->no_analog && has_cdefine_beep(codec)) {
4912 err = snd_hda_attach_beep_device(codec, 0x1);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004913 if (err < 0)
4914 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004915 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004916 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004917
4918 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4919
Takashi Iwai1d045db2011-07-07 18:23:21 +02004920 codec->patch_ops = alc_patch_ops;
Takashi Iwai42399f72011-11-07 17:18:44 +01004921 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004922 spec->shutup = alc_eapd_shutup;
4923
Takashi Iwai1d045db2011-07-07 18:23:21 +02004924#ifdef CONFIG_SND_HDA_POWER_SAVE
4925 if (!spec->loopback.amplist)
4926 spec->loopback.amplist = alc262_loopbacks;
4927#endif
4928
4929 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004930
4931 error:
4932 alc_free(codec);
4933 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004934}
4935
4936/*
4937 * ALC268
4938 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004939/* bind Beep switches of both NID 0x0f and 0x10 */
4940static const struct hda_bind_ctls alc268_bind_beep_sw = {
4941 .ops = &snd_hda_bind_sw,
4942 .values = {
4943 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4944 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4945 0
4946 },
4947};
4948
4949static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4950 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4951 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4952 { }
4953};
4954
4955/* set PCBEEP vol = 0, mute connections */
4956static const struct hda_verb alc268_beep_init_verbs[] = {
4957 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4958 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4959 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4960 { }
4961};
4962
4963/*
4964 * BIOS auto configuration
4965 */
4966static int alc268_parse_auto_config(struct hda_codec *codec)
4967{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004968 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004969 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004970 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4971 if (err > 0) {
4972 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4973 add_mixer(spec, alc268_beep_mixer);
4974 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004975 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004976 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004977 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004978}
4979
Takashi Iwai1d045db2011-07-07 18:23:21 +02004980/*
4981 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004982static int patch_alc268(struct hda_codec *codec)
4983{
4984 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004985 int i, has_beep, err;
4986
4987 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4988 if (spec == NULL)
4989 return -ENOMEM;
4990
4991 codec->spec = spec;
4992
4993 /* ALC268 has no aa-loopback mixer */
4994
Takashi Iwai6ebb8052011-08-16 15:15:40 +02004995 /* automatic parse from the BIOS config */
4996 err = alc268_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02004997 if (err < 0)
4998 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004999
Takashi Iwai1d045db2011-07-07 18:23:21 +02005000 has_beep = 0;
5001 for (i = 0; i < spec->num_mixers; i++) {
5002 if (spec->mixers[i] == alc268_beep_mixer) {
5003 has_beep = 1;
5004 break;
5005 }
5006 }
5007
5008 if (has_beep) {
5009 err = snd_hda_attach_beep_device(codec, 0x1);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005010 if (err < 0)
5011 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005012 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
5013 /* override the amp caps for beep generator */
5014 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
5015 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
5016 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
5017 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5018 (0 << AC_AMPCAP_MUTE_SHIFT));
5019 }
5020
Takashi Iwai60a6a842011-07-27 14:01:24 +02005021 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005022 alc_auto_fill_adc_caps(codec);
5023 alc_rebuild_imux_for_auto_mic(codec);
5024 alc_remove_invalid_adc_nids(codec);
5025 }
5026
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005027 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005028 set_capture_mixer(codec);
5029
Takashi Iwai1d045db2011-07-07 18:23:21 +02005030 codec->patch_ops = alc_patch_ops;
Takashi Iwai6ebb8052011-08-16 15:15:40 +02005031 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005032 spec->shutup = alc_eapd_shutup;
5033
Takashi Iwai1d045db2011-07-07 18:23:21 +02005034 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005035
5036 error:
5037 alc_free(codec);
5038 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005039}
5040
5041/*
5042 * ALC269
5043 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005044#ifdef CONFIG_SND_HDA_POWER_SAVE
5045#define alc269_loopbacks alc880_loopbacks
5046#endif
5047
5048static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
5049 .substreams = 1,
5050 .channels_min = 2,
5051 .channels_max = 8,
5052 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
5053 /* NID is set in alc_build_pcms */
5054 .ops = {
5055 .open = alc_playback_pcm_open,
5056 .prepare = alc_playback_pcm_prepare,
5057 .cleanup = alc_playback_pcm_cleanup
5058 },
5059};
5060
5061static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
5062 .substreams = 1,
5063 .channels_min = 2,
5064 .channels_max = 2,
5065 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
5066 /* NID is set in alc_build_pcms */
5067};
5068
5069#ifdef CONFIG_SND_HDA_POWER_SAVE
5070static int alc269_mic2_for_mute_led(struct hda_codec *codec)
5071{
5072 switch (codec->subsystem_id) {
5073 case 0x103c1586:
5074 return 1;
5075 }
5076 return 0;
5077}
5078
5079static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
5080{
5081 /* update mute-LED according to the speaker mute state */
5082 if (nid == 0x01 || nid == 0x14) {
5083 int pinval;
5084 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
5085 HDA_AMP_MUTE)
5086 pinval = 0x24;
5087 else
5088 pinval = 0x20;
5089 /* mic2 vref pin is used for mute LED control */
5090 snd_hda_codec_update_cache(codec, 0x19, 0,
5091 AC_VERB_SET_PIN_WIDGET_CONTROL,
5092 pinval);
5093 }
5094 return alc_check_power_status(codec, nid);
5095}
5096#endif /* CONFIG_SND_HDA_POWER_SAVE */
5097
5098/* different alc269-variants */
5099enum {
5100 ALC269_TYPE_ALC269VA,
5101 ALC269_TYPE_ALC269VB,
5102 ALC269_TYPE_ALC269VC,
5103};
5104
5105/*
5106 * BIOS auto configuration
5107 */
5108static int alc269_parse_auto_config(struct hda_codec *codec)
5109{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005110 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005111 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
5112 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5113 struct alc_spec *spec = codec->spec;
5114 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
5115 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005116
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005117 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005118}
5119
Takashi Iwai1d045db2011-07-07 18:23:21 +02005120static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
5121{
5122 int val = alc_read_coef_idx(codec, 0x04);
5123 if (power_up)
5124 val |= 1 << 11;
5125 else
5126 val &= ~(1 << 11);
5127 alc_write_coef_idx(codec, 0x04, val);
5128}
5129
5130static void alc269_shutup(struct hda_codec *codec)
5131{
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005132 if ((alc_get_coef0(codec) & 0x00ff) == 0x017)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005133 alc269_toggle_power_output(codec, 0);
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005134 if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005135 alc269_toggle_power_output(codec, 0);
5136 msleep(150);
5137 }
5138}
5139
Takashi Iwai2a439522011-07-26 09:52:50 +02005140#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02005141static int alc269_resume(struct hda_codec *codec)
5142{
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005143 if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005144 alc269_toggle_power_output(codec, 0);
5145 msleep(150);
5146 }
5147
5148 codec->patch_ops.init(codec);
5149
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005150 if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005151 alc269_toggle_power_output(codec, 1);
5152 msleep(200);
5153 }
5154
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005155 if ((alc_get_coef0(codec) & 0x00ff) == 0x018)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005156 alc269_toggle_power_output(codec, 1);
5157
5158 snd_hda_codec_resume_amp(codec);
5159 snd_hda_codec_resume_cache(codec);
5160 hda_call_check_power_status(codec, 0x01);
5161 return 0;
5162}
Takashi Iwai2a439522011-07-26 09:52:50 +02005163#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005164
5165static void alc269_fixup_hweq(struct hda_codec *codec,
5166 const struct alc_fixup *fix, int action)
5167{
5168 int coef;
5169
5170 if (action != ALC_FIXUP_ACT_INIT)
5171 return;
5172 coef = alc_read_coef_idx(codec, 0x1e);
5173 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
5174}
5175
5176static void alc271_fixup_dmic(struct hda_codec *codec,
5177 const struct alc_fixup *fix, int action)
5178{
5179 static const struct hda_verb verbs[] = {
5180 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
5181 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
5182 {}
5183 };
5184 unsigned int cfg;
5185
5186 if (strcmp(codec->chip_name, "ALC271X"))
5187 return;
5188 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
5189 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
5190 snd_hda_sequence_write(codec, verbs);
5191}
5192
Takashi Iwai017f2a12011-07-09 14:42:25 +02005193static void alc269_fixup_pcm_44k(struct hda_codec *codec,
5194 const struct alc_fixup *fix, int action)
5195{
5196 struct alc_spec *spec = codec->spec;
5197
5198 if (action != ALC_FIXUP_ACT_PROBE)
5199 return;
5200
5201 /* Due to a hardware problem on Lenovo Ideadpad, we need to
5202 * fix the sample rate of analog I/O to 44.1kHz
5203 */
5204 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
5205 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
5206}
5207
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02005208static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
5209 const struct alc_fixup *fix, int action)
5210{
5211 int coef;
5212
5213 if (action != ALC_FIXUP_ACT_INIT)
5214 return;
5215 /* The digital-mic unit sends PDM (differential signal) instead of
5216 * the standard PCM, thus you can't record a valid mono stream as is.
5217 * Below is a workaround specific to ALC269 to control the dmic
5218 * signal source as mono.
5219 */
5220 coef = alc_read_coef_idx(codec, 0x07);
5221 alc_write_coef_idx(codec, 0x07, coef | 0x80);
5222}
5223
Takashi Iwai24519912011-08-16 15:08:49 +02005224static void alc269_quanta_automute(struct hda_codec *codec)
5225{
David Henningsson42cf0d02011-09-20 12:04:56 +02005226 update_outputs(codec);
Takashi Iwai24519912011-08-16 15:08:49 +02005227
5228 snd_hda_codec_write(codec, 0x20, 0,
5229 AC_VERB_SET_COEF_INDEX, 0x0c);
5230 snd_hda_codec_write(codec, 0x20, 0,
5231 AC_VERB_SET_PROC_COEF, 0x680);
5232
5233 snd_hda_codec_write(codec, 0x20, 0,
5234 AC_VERB_SET_COEF_INDEX, 0x0c);
5235 snd_hda_codec_write(codec, 0x20, 0,
5236 AC_VERB_SET_PROC_COEF, 0x480);
5237}
5238
5239static void alc269_fixup_quanta_mute(struct hda_codec *codec,
5240 const struct alc_fixup *fix, int action)
5241{
5242 struct alc_spec *spec = codec->spec;
5243 if (action != ALC_FIXUP_ACT_PROBE)
5244 return;
5245 spec->automute_hook = alc269_quanta_automute;
5246}
5247
Takashi Iwai1d045db2011-07-07 18:23:21 +02005248enum {
5249 ALC269_FIXUP_SONY_VAIO,
5250 ALC275_FIXUP_SONY_VAIO_GPIO2,
5251 ALC269_FIXUP_DELL_M101Z,
5252 ALC269_FIXUP_SKU_IGNORE,
5253 ALC269_FIXUP_ASUS_G73JW,
5254 ALC269_FIXUP_LENOVO_EAPD,
5255 ALC275_FIXUP_SONY_HWEQ,
5256 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02005257 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02005258 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai24519912011-08-16 15:08:49 +02005259 ALC269_FIXUP_QUANTA_MUTE,
5260 ALC269_FIXUP_LIFEBOOK,
Takashi Iwaia4297b52011-08-23 18:40:12 +02005261 ALC269_FIXUP_AMIC,
5262 ALC269_FIXUP_DMIC,
5263 ALC269VB_FIXUP_AMIC,
5264 ALC269VB_FIXUP_DMIC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02005265};
5266
5267static const struct alc_fixup alc269_fixups[] = {
5268 [ALC269_FIXUP_SONY_VAIO] = {
5269 .type = ALC_FIXUP_VERBS,
5270 .v.verbs = (const struct hda_verb[]) {
5271 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
5272 {}
5273 }
5274 },
5275 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
5276 .type = ALC_FIXUP_VERBS,
5277 .v.verbs = (const struct hda_verb[]) {
5278 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
5279 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
5280 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
5281 { }
5282 },
5283 .chained = true,
5284 .chain_id = ALC269_FIXUP_SONY_VAIO
5285 },
5286 [ALC269_FIXUP_DELL_M101Z] = {
5287 .type = ALC_FIXUP_VERBS,
5288 .v.verbs = (const struct hda_verb[]) {
5289 /* Enables internal speaker */
5290 {0x20, AC_VERB_SET_COEF_INDEX, 13},
5291 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
5292 {}
5293 }
5294 },
5295 [ALC269_FIXUP_SKU_IGNORE] = {
5296 .type = ALC_FIXUP_SKU,
5297 .v.sku = ALC_FIXUP_SKU_IGNORE,
5298 },
5299 [ALC269_FIXUP_ASUS_G73JW] = {
5300 .type = ALC_FIXUP_PINS,
5301 .v.pins = (const struct alc_pincfg[]) {
5302 { 0x17, 0x99130111 }, /* subwoofer */
5303 { }
5304 }
5305 },
5306 [ALC269_FIXUP_LENOVO_EAPD] = {
5307 .type = ALC_FIXUP_VERBS,
5308 .v.verbs = (const struct hda_verb[]) {
5309 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5310 {}
5311 }
5312 },
5313 [ALC275_FIXUP_SONY_HWEQ] = {
5314 .type = ALC_FIXUP_FUNC,
5315 .v.func = alc269_fixup_hweq,
5316 .chained = true,
5317 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
5318 },
5319 [ALC271_FIXUP_DMIC] = {
5320 .type = ALC_FIXUP_FUNC,
5321 .v.func = alc271_fixup_dmic,
5322 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02005323 [ALC269_FIXUP_PCM_44K] = {
5324 .type = ALC_FIXUP_FUNC,
5325 .v.func = alc269_fixup_pcm_44k,
5326 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02005327 [ALC269_FIXUP_STEREO_DMIC] = {
5328 .type = ALC_FIXUP_FUNC,
5329 .v.func = alc269_fixup_stereo_dmic,
5330 },
Takashi Iwai24519912011-08-16 15:08:49 +02005331 [ALC269_FIXUP_QUANTA_MUTE] = {
5332 .type = ALC_FIXUP_FUNC,
5333 .v.func = alc269_fixup_quanta_mute,
5334 },
5335 [ALC269_FIXUP_LIFEBOOK] = {
5336 .type = ALC_FIXUP_PINS,
5337 .v.pins = (const struct alc_pincfg[]) {
5338 { 0x1a, 0x2101103f }, /* dock line-out */
5339 { 0x1b, 0x23a11040 }, /* dock mic-in */
5340 { }
5341 },
5342 .chained = true,
5343 .chain_id = ALC269_FIXUP_QUANTA_MUTE
5344 },
Takashi Iwaia4297b52011-08-23 18:40:12 +02005345 [ALC269_FIXUP_AMIC] = {
5346 .type = ALC_FIXUP_PINS,
5347 .v.pins = (const struct alc_pincfg[]) {
5348 { 0x14, 0x99130110 }, /* speaker */
5349 { 0x15, 0x0121401f }, /* HP out */
5350 { 0x18, 0x01a19c20 }, /* mic */
5351 { 0x19, 0x99a3092f }, /* int-mic */
5352 { }
5353 },
5354 },
5355 [ALC269_FIXUP_DMIC] = {
5356 .type = ALC_FIXUP_PINS,
5357 .v.pins = (const struct alc_pincfg[]) {
5358 { 0x12, 0x99a3092f }, /* int-mic */
5359 { 0x14, 0x99130110 }, /* speaker */
5360 { 0x15, 0x0121401f }, /* HP out */
5361 { 0x18, 0x01a19c20 }, /* mic */
5362 { }
5363 },
5364 },
5365 [ALC269VB_FIXUP_AMIC] = {
5366 .type = ALC_FIXUP_PINS,
5367 .v.pins = (const struct alc_pincfg[]) {
5368 { 0x14, 0x99130110 }, /* speaker */
5369 { 0x18, 0x01a19c20 }, /* mic */
5370 { 0x19, 0x99a3092f }, /* int-mic */
5371 { 0x21, 0x0121401f }, /* HP out */
5372 { }
5373 },
5374 },
David Henningsson2267ea92012-01-03 08:45:56 +01005375 [ALC269VB_FIXUP_DMIC] = {
Takashi Iwaia4297b52011-08-23 18:40:12 +02005376 .type = ALC_FIXUP_PINS,
5377 .v.pins = (const struct alc_pincfg[]) {
5378 { 0x12, 0x99a3092f }, /* int-mic */
5379 { 0x14, 0x99130110 }, /* speaker */
5380 { 0x18, 0x01a19c20 }, /* mic */
5381 { 0x21, 0x0121401f }, /* HP out */
5382 { }
5383 },
5384 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02005385};
5386
5387static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02005388 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02005389 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
5390 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
5391 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
5392 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
5393 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005394 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
5395 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
5396 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
5397 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
5398 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
5399 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
Takashi Iwai24519912011-08-16 15:08:49 +02005400 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005401 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
5402 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
5403 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
5404 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
5405 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai24519912011-08-16 15:08:49 +02005406 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02005407 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005408 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
Takashi Iwaia4297b52011-08-23 18:40:12 +02005409
5410#if 1
5411 /* Below is a quirk table taken from the old code.
5412 * Basically the device should work as is without the fixup table.
5413 * If BIOS doesn't give a proper info, enable the corresponding
5414 * fixup entry.
5415 */
5416 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
5417 ALC269_FIXUP_AMIC),
5418 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
Takashi Iwaia4297b52011-08-23 18:40:12 +02005419 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
5420 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
5421 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
5422 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC),
5423 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC),
5424 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC),
5425 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC),
5426 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC),
5427 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC),
5428 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC),
5429 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC),
5430 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC),
5431 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC),
5432 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC),
5433 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC),
5434 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC),
5435 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC),
5436 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC),
5437 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC),
5438 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC),
5439 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC),
5440 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC),
5441 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC),
5442 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC),
5443 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC),
5444 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC),
5445 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC),
5446 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC),
5447 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC),
5448 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC),
5449 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC),
5450 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC),
5451 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC),
5452 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC),
5453 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC),
5454 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC),
5455 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC),
5456 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC),
5457#endif
5458 {}
5459};
5460
5461static const struct alc_model_fixup alc269_fixup_models[] = {
5462 {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
5463 {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
Takashi Iwai1d045db2011-07-07 18:23:21 +02005464 {}
5465};
5466
5467
5468static int alc269_fill_coef(struct hda_codec *codec)
5469{
5470 int val;
5471
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005472 if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005473 alc_write_coef_idx(codec, 0xf, 0x960b);
5474 alc_write_coef_idx(codec, 0xe, 0x8817);
5475 }
5476
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005477 if ((alc_get_coef0(codec) & 0x00ff) == 0x016) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005478 alc_write_coef_idx(codec, 0xf, 0x960b);
5479 alc_write_coef_idx(codec, 0xe, 0x8814);
5480 }
5481
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005482 if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005483 val = alc_read_coef_idx(codec, 0x04);
5484 /* Power up output pin */
5485 alc_write_coef_idx(codec, 0x04, val | (1<<11));
5486 }
5487
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005488 if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005489 val = alc_read_coef_idx(codec, 0xd);
5490 if ((val & 0x0c00) >> 10 != 0x1) {
5491 /* Capless ramp up clock control */
5492 alc_write_coef_idx(codec, 0xd, val | (1<<10));
5493 }
5494 val = alc_read_coef_idx(codec, 0x17);
5495 if ((val & 0x01c0) >> 6 != 0x4) {
5496 /* Class D power on reset */
5497 alc_write_coef_idx(codec, 0x17, val | (1<<7));
5498 }
5499 }
5500
5501 val = alc_read_coef_idx(codec, 0xd); /* Class D */
5502 alc_write_coef_idx(codec, 0xd, val | (1<<14));
5503
5504 val = alc_read_coef_idx(codec, 0x4); /* HP */
5505 alc_write_coef_idx(codec, 0x4, val | (1<<11));
5506
5507 return 0;
5508}
5509
5510/*
5511 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005512static int patch_alc269(struct hda_codec *codec)
5513{
5514 struct alc_spec *spec;
Takashi Iwai20ca0c32011-10-17 16:00:35 +02005515 int err = 0;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005516
5517 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5518 if (spec == NULL)
5519 return -ENOMEM;
5520
5521 codec->spec = spec;
5522
5523 spec->mixer_nid = 0x0b;
5524
5525 alc_auto_parse_customize_define(codec);
5526
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005527 err = alc_codec_rename_from_preset(codec);
5528 if (err < 0)
5529 goto error;
5530
Takashi Iwai1d045db2011-07-07 18:23:21 +02005531 if (codec->vendor_id == 0x10ec0269) {
5532 spec->codec_variant = ALC269_TYPE_ALC269VA;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005533 switch (alc_get_coef0(codec) & 0x00f0) {
5534 case 0x0010:
Takashi Iwai1d045db2011-07-07 18:23:21 +02005535 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005536 spec->cdefine.platform_type == 1)
Takashi Iwai20ca0c32011-10-17 16:00:35 +02005537 err = alc_codec_rename(codec, "ALC271X");
Takashi Iwai1d045db2011-07-07 18:23:21 +02005538 spec->codec_variant = ALC269_TYPE_ALC269VB;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005539 break;
5540 case 0x0020:
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005541 if (codec->bus->pci->subsystem_vendor == 0x17aa &&
5542 codec->bus->pci->subsystem_device == 0x21f3)
Takashi Iwai20ca0c32011-10-17 16:00:35 +02005543 err = alc_codec_rename(codec, "ALC3202");
Takashi Iwai1d045db2011-07-07 18:23:21 +02005544 spec->codec_variant = ALC269_TYPE_ALC269VC;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005545 break;
5546 default:
Takashi Iwai1d045db2011-07-07 18:23:21 +02005547 alc_fix_pll_init(codec, 0x20, 0x04, 15);
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005548 }
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005549 if (err < 0)
5550 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005551 alc269_fill_coef(codec);
5552 }
5553
Takashi Iwaia4297b52011-08-23 18:40:12 +02005554 alc_pick_fixup(codec, alc269_fixup_models,
5555 alc269_fixup_tbl, alc269_fixups);
5556 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005557
Takashi Iwaia4297b52011-08-23 18:40:12 +02005558 /* automatic parse from the BIOS config */
5559 err = alc269_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005560 if (err < 0)
5561 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005562
Takashi Iwai60a6a842011-07-27 14:01:24 +02005563 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005564 alc_auto_fill_adc_caps(codec);
5565 alc_rebuild_imux_for_auto_mic(codec);
5566 alc_remove_invalid_adc_nids(codec);
5567 }
5568
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005569 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005570 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005571
5572 if (!spec->no_analog && has_cdefine_beep(codec)) {
5573 err = snd_hda_attach_beep_device(codec, 0x1);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005574 if (err < 0)
5575 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005576 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005577 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005578
5579 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5580
Takashi Iwai1d045db2011-07-07 18:23:21 +02005581 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02005582#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02005583 codec->patch_ops.resume = alc269_resume;
5584#endif
Takashi Iwaia4297b52011-08-23 18:40:12 +02005585 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005586 spec->shutup = alc269_shutup;
5587
Takashi Iwai1d045db2011-07-07 18:23:21 +02005588#ifdef CONFIG_SND_HDA_POWER_SAVE
5589 if (!spec->loopback.amplist)
5590 spec->loopback.amplist = alc269_loopbacks;
5591 if (alc269_mic2_for_mute_led(codec))
5592 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
5593#endif
5594
5595 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005596
5597 error:
5598 alc_free(codec);
5599 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005600}
5601
5602/*
5603 * ALC861
5604 */
5605
Takashi Iwai1d045db2011-07-07 18:23:21 +02005606static int alc861_parse_auto_config(struct hda_codec *codec)
5607{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005608 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005609 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
5610 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005611}
5612
Takashi Iwai1d045db2011-07-07 18:23:21 +02005613#ifdef CONFIG_SND_HDA_POWER_SAVE
5614static const struct hda_amp_list alc861_loopbacks[] = {
5615 { 0x15, HDA_INPUT, 0 },
5616 { 0x15, HDA_INPUT, 1 },
5617 { 0x15, HDA_INPUT, 2 },
5618 { 0x15, HDA_INPUT, 3 },
5619 { } /* end */
5620};
5621#endif
5622
5623
5624/* Pin config fixes */
5625enum {
5626 PINFIX_FSC_AMILO_PI1505,
Takashi Iwai3b25eb62012-01-25 09:55:46 +01005627 PINFIX_ASUS_A6RP,
Takashi Iwai1d045db2011-07-07 18:23:21 +02005628};
5629
Takashi Iwai31150f22012-01-30 10:54:08 +01005630/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
5631static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
5632 const struct alc_fixup *fix, int action)
5633{
5634 struct alc_spec *spec = codec->spec;
5635 unsigned int val;
5636
5637 if (action != ALC_FIXUP_ACT_INIT)
5638 return;
5639 val = snd_hda_codec_read(codec, 0x0f, 0,
5640 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
5641 if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
5642 val |= AC_PINCTL_IN_EN;
5643 val |= AC_PINCTL_VREF_50;
5644 snd_hda_codec_write(codec, 0x0f, 0,
5645 AC_VERB_SET_PIN_WIDGET_CONTROL, val);
5646 spec->keep_vref_in_automute = 1;
5647}
5648
Takashi Iwai1d045db2011-07-07 18:23:21 +02005649static const struct alc_fixup alc861_fixups[] = {
5650 [PINFIX_FSC_AMILO_PI1505] = {
5651 .type = ALC_FIXUP_PINS,
5652 .v.pins = (const struct alc_pincfg[]) {
5653 { 0x0b, 0x0221101f }, /* HP */
5654 { 0x0f, 0x90170310 }, /* speaker */
5655 { }
5656 }
5657 },
Takashi Iwai3b25eb62012-01-25 09:55:46 +01005658 [PINFIX_ASUS_A6RP] = {
Takashi Iwai31150f22012-01-30 10:54:08 +01005659 .type = ALC_FIXUP_FUNC,
5660 .v.func = alc861_fixup_asus_amp_vref_0f,
Takashi Iwai3b25eb62012-01-25 09:55:46 +01005661 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02005662};
5663
5664static const struct snd_pci_quirk alc861_fixup_tbl[] = {
Takashi Iwai31150f22012-01-30 10:54:08 +01005665 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP),
Jaroslav Kysela416846d2012-02-07 14:18:14 +01005666 SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP),
Takashi Iwaib3a81522012-01-26 15:56:16 +01005667 SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005668 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
5669 {}
5670};
5671
5672/*
5673 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005674static int patch_alc861(struct hda_codec *codec)
5675{
5676 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005677 int err;
5678
5679 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5680 if (spec == NULL)
5681 return -ENOMEM;
5682
5683 codec->spec = spec;
5684
5685 spec->mixer_nid = 0x15;
5686
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005687 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
5688 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005689
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005690 /* automatic parse from the BIOS config */
5691 err = alc861_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005692 if (err < 0)
5693 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005694
Takashi Iwai60a6a842011-07-27 14:01:24 +02005695 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005696 alc_auto_fill_adc_caps(codec);
5697 alc_rebuild_imux_for_auto_mic(codec);
5698 alc_remove_invalid_adc_nids(codec);
5699 }
5700
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005701 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005702 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005703
5704 if (!spec->no_analog) {
5705 err = snd_hda_attach_beep_device(codec, 0x23);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005706 if (err < 0)
5707 goto error;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005708 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
5709 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005710
Takashi Iwai1d045db2011-07-07 18:23:21 +02005711 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5712
5713 codec->patch_ops = alc_patch_ops;
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005714 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005715#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005716 spec->power_hook = alc_power_eapd;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005717 if (!spec->loopback.amplist)
5718 spec->loopback.amplist = alc861_loopbacks;
5719#endif
5720
5721 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005722
5723 error:
5724 alc_free(codec);
5725 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005726}
5727
5728/*
5729 * ALC861-VD support
5730 *
5731 * Based on ALC882
5732 *
5733 * In addition, an independent DAC
5734 */
5735#ifdef CONFIG_SND_HDA_POWER_SAVE
5736#define alc861vd_loopbacks alc880_loopbacks
5737#endif
5738
Takashi Iwai1d045db2011-07-07 18:23:21 +02005739static int alc861vd_parse_auto_config(struct hda_codec *codec)
5740{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005741 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005742 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5743 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005744}
5745
Takashi Iwai1d045db2011-07-07 18:23:21 +02005746enum {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005747 ALC660VD_FIX_ASUS_GPIO1,
5748 ALC861VD_FIX_DALLAS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02005749};
5750
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005751/* exclude VREF80 */
5752static void alc861vd_fixup_dallas(struct hda_codec *codec,
5753 const struct alc_fixup *fix, int action)
5754{
5755 if (action == ALC_FIXUP_ACT_PRE_PROBE) {
5756 snd_hda_override_pin_caps(codec, 0x18, 0x00001714);
5757 snd_hda_override_pin_caps(codec, 0x19, 0x0000171c);
5758 }
5759}
5760
Takashi Iwai1d045db2011-07-07 18:23:21 +02005761static const struct alc_fixup alc861vd_fixups[] = {
5762 [ALC660VD_FIX_ASUS_GPIO1] = {
5763 .type = ALC_FIXUP_VERBS,
5764 .v.verbs = (const struct hda_verb[]) {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005765 /* reset GPIO1 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005766 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5767 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5768 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5769 { }
5770 }
5771 },
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005772 [ALC861VD_FIX_DALLAS] = {
5773 .type = ALC_FIXUP_FUNC,
5774 .v.func = alc861vd_fixup_dallas,
5775 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02005776};
5777
5778static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005779 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005780 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005781 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005782 {}
5783};
5784
5785static const struct hda_verb alc660vd_eapd_verbs[] = {
5786 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
5787 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
5788 { }
5789};
5790
5791/*
5792 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005793static int patch_alc861vd(struct hda_codec *codec)
5794{
5795 struct alc_spec *spec;
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005796 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005797
5798 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5799 if (spec == NULL)
5800 return -ENOMEM;
5801
5802 codec->spec = spec;
5803
5804 spec->mixer_nid = 0x0b;
5805
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005806 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
5807 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005808
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005809 /* automatic parse from the BIOS config */
5810 err = alc861vd_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005811 if (err < 0)
5812 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005813
Takashi Iwai1d045db2011-07-07 18:23:21 +02005814 if (codec->vendor_id == 0x10ec0660) {
5815 /* always turn on EAPD */
5816 add_verb(spec, alc660vd_eapd_verbs);
5817 }
5818
Takashi Iwai60a6a842011-07-27 14:01:24 +02005819 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005820 alc_auto_fill_adc_caps(codec);
5821 alc_rebuild_imux_for_auto_mic(codec);
5822 alc_remove_invalid_adc_nids(codec);
5823 }
5824
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005825 if (!spec->no_analog && !spec->cap_mixer)
5826 set_capture_mixer(codec);
5827
5828 if (!spec->no_analog) {
5829 err = snd_hda_attach_beep_device(codec, 0x23);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005830 if (err < 0)
5831 goto error;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005832 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5833 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005834
Takashi Iwai1d045db2011-07-07 18:23:21 +02005835 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5836
5837 codec->patch_ops = alc_patch_ops;
5838
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005839 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005840 spec->shutup = alc_eapd_shutup;
5841#ifdef CONFIG_SND_HDA_POWER_SAVE
5842 if (!spec->loopback.amplist)
5843 spec->loopback.amplist = alc861vd_loopbacks;
5844#endif
5845
5846 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005847
5848 error:
5849 alc_free(codec);
5850 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005851}
5852
5853/*
5854 * ALC662 support
5855 *
5856 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5857 * configuration. Each pin widget can choose any input DACs and a mixer.
5858 * Each ADC is connected from a mixer of all inputs. This makes possible
5859 * 6-channel independent captures.
5860 *
5861 * In addition, an independent DAC for the multi-playback (not used in this
5862 * driver yet).
5863 */
5864#ifdef CONFIG_SND_HDA_POWER_SAVE
5865#define alc662_loopbacks alc880_loopbacks
5866#endif
5867
5868/*
5869 * BIOS auto configuration
5870 */
5871
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005872static int alc662_parse_auto_config(struct hda_codec *codec)
5873{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005874 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005875 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5876 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5877 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005878
Kailang Yang6227cdc2010-02-25 08:36:52 +01005879 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5880 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005881 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005882 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005883 ssids = alc662_ssids;
5884 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005885}
5886
Todd Broch6be79482010-12-07 16:51:05 -08005887static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005888 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005889{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005890 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005891 return;
Todd Broch6be79482010-12-07 16:51:05 -08005892 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5893 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5894 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5895 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5896 (0 << AC_AMPCAP_MUTE_SHIFT)))
5897 printk(KERN_WARNING
5898 "hda_codec: failed to override amp caps for NID 0x2\n");
5899}
5900
David Henningsson6cb3b702010-09-09 08:51:44 +02005901enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005902 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005903 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005904 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005905 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005906 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005907 ALC662_FIXUP_HP_RP5800,
Takashi Iwai53c334a2011-08-23 18:27:14 +02005908 ALC662_FIXUP_ASUS_MODE1,
5909 ALC662_FIXUP_ASUS_MODE2,
5910 ALC662_FIXUP_ASUS_MODE3,
5911 ALC662_FIXUP_ASUS_MODE4,
5912 ALC662_FIXUP_ASUS_MODE5,
5913 ALC662_FIXUP_ASUS_MODE6,
5914 ALC662_FIXUP_ASUS_MODE7,
5915 ALC662_FIXUP_ASUS_MODE8,
David Henningsson6cb3b702010-09-09 08:51:44 +02005916};
5917
5918static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005919 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005920 .type = ALC_FIXUP_PINS,
5921 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005922 { 0x15, 0x99130112 }, /* subwoofer */
5923 { }
5924 }
5925 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005926 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005927 .type = ALC_FIXUP_PINS,
5928 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005929 { 0x17, 0x99130112 }, /* subwoofer */
5930 { }
5931 }
5932 },
Todd Broch6be79482010-12-07 16:51:05 -08005933 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005934 .type = ALC_FIXUP_FUNC,
5935 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005936 },
5937 [ALC662_FIXUP_CZC_P10T] = {
5938 .type = ALC_FIXUP_VERBS,
5939 .v.verbs = (const struct hda_verb[]) {
5940 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5941 {}
5942 }
5943 },
David Henningsson94024cd2011-04-29 14:10:55 +02005944 [ALC662_FIXUP_SKU_IGNORE] = {
5945 .type = ALC_FIXUP_SKU,
5946 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005947 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005948 [ALC662_FIXUP_HP_RP5800] = {
5949 .type = ALC_FIXUP_PINS,
5950 .v.pins = (const struct alc_pincfg[]) {
5951 { 0x14, 0x0221201f }, /* HP out */
5952 { }
5953 },
5954 .chained = true,
5955 .chain_id = ALC662_FIXUP_SKU_IGNORE
5956 },
Takashi Iwai53c334a2011-08-23 18:27:14 +02005957 [ALC662_FIXUP_ASUS_MODE1] = {
5958 .type = ALC_FIXUP_PINS,
5959 .v.pins = (const struct alc_pincfg[]) {
5960 { 0x14, 0x99130110 }, /* speaker */
5961 { 0x18, 0x01a19c20 }, /* mic */
5962 { 0x19, 0x99a3092f }, /* int-mic */
5963 { 0x21, 0x0121401f }, /* HP out */
5964 { }
5965 },
5966 .chained = true,
5967 .chain_id = ALC662_FIXUP_SKU_IGNORE
5968 },
5969 [ALC662_FIXUP_ASUS_MODE2] = {
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005970 .type = ALC_FIXUP_PINS,
5971 .v.pins = (const struct alc_pincfg[]) {
5972 { 0x14, 0x99130110 }, /* speaker */
5973 { 0x18, 0x01a19820 }, /* mic */
5974 { 0x19, 0x99a3092f }, /* int-mic */
5975 { 0x1b, 0x0121401f }, /* HP out */
5976 { }
5977 },
Takashi Iwai53c334a2011-08-23 18:27:14 +02005978 .chained = true,
5979 .chain_id = ALC662_FIXUP_SKU_IGNORE
5980 },
5981 [ALC662_FIXUP_ASUS_MODE3] = {
5982 .type = ALC_FIXUP_PINS,
5983 .v.pins = (const struct alc_pincfg[]) {
5984 { 0x14, 0x99130110 }, /* speaker */
5985 { 0x15, 0x0121441f }, /* HP */
5986 { 0x18, 0x01a19840 }, /* mic */
5987 { 0x19, 0x99a3094f }, /* int-mic */
5988 { 0x21, 0x01211420 }, /* HP2 */
5989 { }
5990 },
5991 .chained = true,
5992 .chain_id = ALC662_FIXUP_SKU_IGNORE
5993 },
5994 [ALC662_FIXUP_ASUS_MODE4] = {
5995 .type = ALC_FIXUP_PINS,
5996 .v.pins = (const struct alc_pincfg[]) {
5997 { 0x14, 0x99130110 }, /* speaker */
5998 { 0x16, 0x99130111 }, /* speaker */
5999 { 0x18, 0x01a19840 }, /* mic */
6000 { 0x19, 0x99a3094f }, /* int-mic */
6001 { 0x21, 0x0121441f }, /* HP */
6002 { }
6003 },
6004 .chained = true,
6005 .chain_id = ALC662_FIXUP_SKU_IGNORE
6006 },
6007 [ALC662_FIXUP_ASUS_MODE5] = {
6008 .type = ALC_FIXUP_PINS,
6009 .v.pins = (const struct alc_pincfg[]) {
6010 { 0x14, 0x99130110 }, /* speaker */
6011 { 0x15, 0x0121441f }, /* HP */
6012 { 0x16, 0x99130111 }, /* speaker */
6013 { 0x18, 0x01a19840 }, /* mic */
6014 { 0x19, 0x99a3094f }, /* int-mic */
6015 { }
6016 },
6017 .chained = true,
6018 .chain_id = ALC662_FIXUP_SKU_IGNORE
6019 },
6020 [ALC662_FIXUP_ASUS_MODE6] = {
6021 .type = ALC_FIXUP_PINS,
6022 .v.pins = (const struct alc_pincfg[]) {
6023 { 0x14, 0x99130110 }, /* speaker */
6024 { 0x15, 0x01211420 }, /* HP2 */
6025 { 0x18, 0x01a19840 }, /* mic */
6026 { 0x19, 0x99a3094f }, /* int-mic */
6027 { 0x1b, 0x0121441f }, /* HP */
6028 { }
6029 },
6030 .chained = true,
6031 .chain_id = ALC662_FIXUP_SKU_IGNORE
6032 },
6033 [ALC662_FIXUP_ASUS_MODE7] = {
6034 .type = ALC_FIXUP_PINS,
6035 .v.pins = (const struct alc_pincfg[]) {
6036 { 0x14, 0x99130110 }, /* speaker */
6037 { 0x17, 0x99130111 }, /* speaker */
6038 { 0x18, 0x01a19840 }, /* mic */
6039 { 0x19, 0x99a3094f }, /* int-mic */
6040 { 0x1b, 0x01214020 }, /* HP */
6041 { 0x21, 0x0121401f }, /* HP */
6042 { }
6043 },
6044 .chained = true,
6045 .chain_id = ALC662_FIXUP_SKU_IGNORE
6046 },
6047 [ALC662_FIXUP_ASUS_MODE8] = {
6048 .type = ALC_FIXUP_PINS,
6049 .v.pins = (const struct alc_pincfg[]) {
6050 { 0x14, 0x99130110 }, /* speaker */
6051 { 0x12, 0x99a30970 }, /* int-mic */
6052 { 0x15, 0x01214020 }, /* HP */
6053 { 0x17, 0x99130111 }, /* speaker */
6054 { 0x18, 0x01a19840 }, /* mic */
6055 { 0x21, 0x0121401f }, /* HP */
6056 { }
6057 },
6058 .chained = true,
6059 .chain_id = ALC662_FIXUP_SKU_IGNORE
Takashi Iwai2996bdb2011-08-18 16:02:24 +02006060 },
David Henningsson6cb3b702010-09-09 08:51:44 +02006061};
6062
Takashi Iwaia9111322011-05-02 11:30:18 +02006063static const struct snd_pci_quirk alc662_fixup_tbl[] = {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006064 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
David Henningssona6c47a82011-02-10 15:39:19 +01006065 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02006066 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04006067 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006068 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Takashi Iwai53c334a2011-08-23 18:27:14 +02006069 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05006070 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06006071 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02006072 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01006073 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
Takashi Iwai53c334a2011-08-23 18:27:14 +02006074
6075#if 0
6076 /* Below is a quirk table taken from the old code.
6077 * Basically the device should work as is without the fixup table.
6078 * If BIOS doesn't give a proper info, enable the corresponding
6079 * fixup entry.
6080 */
6081 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
6082 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
6083 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
6084 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
6085 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6086 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6087 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6088 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
6089 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
6090 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6091 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
6092 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
6093 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
6094 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
6095 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
6096 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6097 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
6098 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
6099 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6100 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6101 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6102 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6103 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
6104 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
6105 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
6106 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6107 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
6108 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6109 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6110 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
6111 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6112 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6113 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
6114 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
6115 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
6116 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
6117 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
6118 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
6119 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
6120 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6121 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
6122 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
6123 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6124 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
6125 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
6126 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
6127 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
6128 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
6129 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6130 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
6131#endif
David Henningsson6cb3b702010-09-09 08:51:44 +02006132 {}
6133};
6134
Todd Broch6be79482010-12-07 16:51:05 -08006135static const struct alc_model_fixup alc662_fixup_models[] = {
6136 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
Takashi Iwai53c334a2011-08-23 18:27:14 +02006137 {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
6138 {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
6139 {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
6140 {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
6141 {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
6142 {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
6143 {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
6144 {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
Todd Broch6be79482010-12-07 16:51:05 -08006145 {}
6146};
David Henningsson6cb3b702010-09-09 08:51:44 +02006147
6148
Takashi Iwai1d045db2011-07-07 18:23:21 +02006149/*
6150 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006151static int patch_alc662(struct hda_codec *codec)
6152{
6153 struct alc_spec *spec;
Takashi Iwai20ca0c32011-10-17 16:00:35 +02006154 int err = 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006155
6156 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6157 if (!spec)
6158 return -ENOMEM;
6159
6160 codec->spec = spec;
6161
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006162 spec->mixer_nid = 0x0b;
6163
Takashi Iwai53c334a2011-08-23 18:27:14 +02006164 /* handle multiple HPs as is */
6165 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
6166
Kailang Yangda00c242010-03-19 11:23:45 +01006167 alc_auto_parse_customize_define(codec);
6168
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02006169 alc_fix_pll_init(codec, 0x20, 0x04, 15);
6170
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006171 err = alc_codec_rename_from_preset(codec);
6172 if (err < 0)
6173 goto error;
6174
Takashi Iwai1bb7e432011-10-17 16:50:59 +02006175 if ((alc_get_coef0(codec) & (1 << 14)) &&
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006176 codec->bus->pci->subsystem_vendor == 0x1025 &&
6177 spec->cdefine.platform_type == 1) {
6178 if (alc_codec_rename(codec, "ALC272X") < 0)
6179 goto error;
Takashi Iwai20ca0c32011-10-17 16:00:35 +02006180 }
Kailang Yang274693f2009-12-03 10:07:50 +01006181
Takashi Iwaib9c51062011-08-24 18:08:07 +02006182 alc_pick_fixup(codec, alc662_fixup_models,
6183 alc662_fixup_tbl, alc662_fixups);
6184 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
6185 /* automatic parse from the BIOS config */
6186 err = alc662_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006187 if (err < 0)
6188 goto error;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006189
Takashi Iwai60a6a842011-07-27 14:01:24 +02006190 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02006191 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02006192 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02006193 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02006194 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006195
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006196 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02006197 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006198
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006199 if (!spec->no_analog && has_cdefine_beep(codec)) {
6200 err = snd_hda_attach_beep_device(codec, 0x1);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006201 if (err < 0)
6202 goto error;
Kailang Yangda00c242010-03-19 11:23:45 +01006203 switch (codec->vendor_id) {
6204 case 0x10ec0662:
6205 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
6206 break;
6207 case 0x10ec0272:
6208 case 0x10ec0663:
6209 case 0x10ec0665:
6210 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
6211 break;
6212 case 0x10ec0273:
6213 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
6214 break;
6215 }
Kailang Yangcec27c82010-02-04 14:18:18 +01006216 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01006217
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006218 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
6219
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006220 codec->patch_ops = alc_patch_ops;
Takashi Iwaib9c51062011-08-24 18:08:07 +02006221 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c716152011-04-07 10:37:16 +02006222 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02006223
Takashi Iwaicb53c622007-08-10 17:21:45 +02006224#ifdef CONFIG_SND_HDA_POWER_SAVE
6225 if (!spec->loopback.amplist)
6226 spec->loopback.amplist = alc662_loopbacks;
6227#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006228
6229 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006230
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006231 error:
6232 alc_free(codec);
6233 return err;
Kailang Yangb478b992011-05-18 11:51:15 +02006234}
6235
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006236/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006237 * ALC680 support
6238 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006239
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006240static int alc680_parse_auto_config(struct hda_codec *codec)
6241{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006242 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006243}
6244
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006245/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006246 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006247static int patch_alc680(struct hda_codec *codec)
6248{
6249 struct alc_spec *spec;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006250 int err;
6251
6252 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6253 if (spec == NULL)
6254 return -ENOMEM;
6255
6256 codec->spec = spec;
6257
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006258 /* ALC680 has no aa-loopback mixer */
6259
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02006260 /* automatic parse from the BIOS config */
6261 err = alc680_parse_auto_config(codec);
6262 if (err < 0) {
6263 alc_free(codec);
6264 return err;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006265 }
6266
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006267 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006268 set_capture_mixer(codec);
6269
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006270 codec->patch_ops = alc_patch_ops;
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02006271 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006272
6273 return 0;
6274}
6275
6276/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277 * patch entries
6278 */
Takashi Iwaia9111322011-05-02 11:30:18 +02006279static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02006280 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006282 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01006283 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02006284 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01006285 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01006286 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02006287 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01006288 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02006289 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006290 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006291 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006292 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
6293 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
6294 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006295 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +02006296 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006297 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
6298 .patch = patch_alc662 },
David Henningssoncc667a72011-10-18 14:07:51 +02006299 { .id = 0x10ec0662, .rev = 0x100300, .name = "ALC662 rev3",
6300 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02006301 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01006302 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01006303 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006304 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006305 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006306 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +02006307 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02006308 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02006309 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02006310 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02006311 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006312 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006313 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
Kailang Yang44426082008-10-15 11:18:05 +02006314 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +02006315 .patch = patch_alc882 },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006316 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +02006317 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01006318 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006319 { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006320 {} /* terminator */
6321};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01006322
6323MODULE_ALIAS("snd-hda-codec-id:10ec*");
6324
6325MODULE_LICENSE("GPL");
6326MODULE_DESCRIPTION("Realtek HD-audio codec");
6327
6328static struct hda_codec_preset_list realtek_list = {
6329 .preset = snd_hda_preset_realtek,
6330 .owner = THIS_MODULE,
6331};
6332
6333static int __init patch_realtek_init(void)
6334{
6335 return snd_hda_add_codec_preset(&realtek_list);
6336}
6337
6338static void __exit patch_realtek_exit(void)
6339{
6340 snd_hda_delete_codec_preset(&realtek_list);
6341}
6342
6343module_init(patch_realtek_init)
6344module_exit(patch_realtek_exit)