blob: 6a4128dc8c5ace957068ce910aaebe509ebe1e95 [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>
30#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020031#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "hda_codec.h"
33#include "hda_local.h"
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090034#include "hda_beep.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Takashi Iwai1d045db2011-07-07 18:23:21 +020036/* unsol event tags */
37#define ALC_FRONT_EVENT 0x01
38#define ALC_DCVOL_EVENT 0x02
39#define ALC_HP_EVENT 0x04
40#define ALC_MIC_EVENT 0x08
Takashi Iwaid4a86d82010-06-23 17:51:26 +020041
Kailang Yangdf694da2005-12-05 19:42:22 +010042/* for GPIO Poll */
43#define GPIO_MASK 0x03
44
Takashi Iwai4a79ba32009-04-22 16:31:35 +020045/* extra amp-initialization sequence types */
46enum {
47 ALC_INIT_NONE,
48 ALC_INIT_DEFAULT,
49 ALC_INIT_GPIO1,
50 ALC_INIT_GPIO2,
51 ALC_INIT_GPIO3,
52};
53
Kailang Yangda00c242010-03-19 11:23:45 +010054struct alc_customize_define {
55 unsigned int sku_cfg;
56 unsigned char port_connectivity;
57 unsigned char check_sum;
58 unsigned char customization;
59 unsigned char external_amp;
60 unsigned int enable_pcbeep:1;
61 unsigned int platform_type:1;
62 unsigned int swap:1;
63 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020064 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010065};
66
Takashi Iwaib5bfbc62011-01-13 14:22:32 +010067struct alc_fixup;
68
Takashi Iwaice764ab2011-04-27 16:35:23 +020069struct alc_multi_io {
70 hda_nid_t pin; /* multi-io widget pin NID */
71 hda_nid_t dac; /* DAC to be connected */
72 unsigned int ctl_in; /* cached input-pin control value */
73};
74
Takashi Iwaid922b512011-04-28 12:18:53 +020075enum {
Takashi Iwai3b8510c2011-04-28 14:03:24 +020076 ALC_AUTOMUTE_PIN, /* change the pin control */
77 ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
78 ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
Takashi Iwaid922b512011-04-28 12:18:53 +020079};
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081struct alc_spec {
82 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020083 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 unsigned int num_mixers;
Takashi Iwaia9111322011-05-02 11:30:18 +020085 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010086 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwai2d9c6482009-10-13 08:06:55 +020088 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +020089 * don't forget NULL
90 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +020091 */
92 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Takashi Iwaiaa563af2009-07-31 10:05:11 +020094 char stream_name_analog[32]; /* analog PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +020095 const struct hda_pcm_stream *stream_analog_playback;
96 const struct hda_pcm_stream *stream_analog_capture;
97 const struct hda_pcm_stream *stream_analog_alt_playback;
98 const struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200100 char stream_name_digital[32]; /* digital PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +0200101 const struct hda_pcm_stream *stream_digital_playback;
102 const struct hda_pcm_stream *stream_digital_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200105 struct hda_multi_out multiout; /* playback set-up
106 * max_channels, dacs must be set
107 * dig_out_nid and hp_nid are optional
108 */
Takashi Iwai63300792008-01-24 15:31:36 +0100109 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100110 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100111 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 /* capture */
114 unsigned int num_adc_nids;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +0200115 const hda_nid_t *adc_nids;
116 const hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200117 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Takashi Iwai1f0f4b82011-06-27 10:52:59 +0200118 hda_nid_t mixer_nid; /* analog-mixer NID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Takashi Iwai840b64c2010-07-13 22:49:01 +0200120 /* capture setup for dynamic dual-adc switch */
Takashi Iwai840b64c2010-07-13 22:49:01 +0200121 hda_nid_t cur_adc;
122 unsigned int cur_adc_stream_tag;
123 unsigned int cur_adc_format;
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200126 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 const struct hda_input_mux *input_mux;
128 unsigned int cur_mux[3];
Takashi Iwai21268962011-07-07 15:01:13 +0200129 hda_nid_t ext_mic_pin;
130 hda_nid_t dock_mic_pin;
131 hda_nid_t int_mic_pin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100134 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200136 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200137 int const_channel_count;
138 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100141 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200142
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200143 /* dynamic controls, init_verbs and input_mux */
144 struct auto_pin_cfg autocfg;
Kailang Yangda00c242010-03-19 11:23:45 +0100145 struct alc_customize_define cdefine;
Takashi Iwai603c4012008-07-30 15:01:44 +0200146 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200147 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200148 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai49535502009-06-30 15:28:30 +0200149 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
150 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai21268962011-07-07 15:01:13 +0200151 hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
152 unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
153 int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
Takashi Iwai834be882006-03-01 14:16:17 +0100154
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100155 /* hooks */
156 void (*init_hook)(struct hda_codec *codec);
157 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100158#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500159 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100160#endif
Takashi Iwai1c716152011-04-07 10:37:16 +0200161 void (*shutup)(struct hda_codec *codec);
Takashi Iwai24519912011-08-16 15:08:49 +0200162 void (*automute_hook)(struct hda_codec *codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100163
Takashi Iwai834be882006-03-01 14:16:17 +0100164 /* for pin sensing */
David Henningsson42cf0d02011-09-20 12:04:56 +0200165 unsigned int hp_jack_present:1;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200166 unsigned int line_jack_present:1;
Takashi Iwaie9427962011-04-28 15:46:07 +0200167 unsigned int master_mute:1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200168 unsigned int auto_mic:1;
Takashi Iwai21268962011-07-07 15:01:13 +0200169 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
David Henningsson42cf0d02011-09-20 12:04:56 +0200170 unsigned int automute_speaker:1; /* automute speaker outputs */
171 unsigned int automute_lo:1; /* automute LO outputs */
172 unsigned int detect_hp:1; /* Headphone detection enabled */
173 unsigned int detect_lo:1; /* Line-out detection enabled */
174 unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
175 unsigned int automute_lo_possible:1; /* there are line outs and HP */
Takashi Iwaicb53c622007-08-10 17:21:45 +0200176
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100177 /* other flags */
178 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai21268962011-07-07 15:01:13 +0200179 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai584c0c42011-03-10 12:51:11 +0100180 unsigned int single_input_src:1;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +0200181 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
Takashi Iwai53c334a2011-08-23 18:27:14 +0200182 unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
Takashi Iwaid922b512011-04-28 12:18:53 +0200183
184 /* auto-mute control */
185 int automute_mode;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200186 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
Takashi Iwaid922b512011-04-28 12:18:53 +0200187
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200188 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200189 int codec_variant; /* flag for other variants */
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100190
Takashi Iwai2134ea42008-01-10 16:53:55 +0100191 /* for virtual master */
192 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200193#ifdef CONFIG_SND_HDA_POWER_SAVE
194 struct hda_loopback_check loopback;
195#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200196
197 /* for PLL fix */
198 hda_nid_t pll_nid;
199 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +0100200
201 /* fix-up list */
202 int fixup_id;
203 const struct alc_fixup *fixup_list;
204 const char *fixup_name;
Takashi Iwaice764ab2011-04-27 16:35:23 +0200205
206 /* multi-io */
207 int multi_ios;
208 struct alc_multi_io multi_io[4];
Takashi Iwai23c09b02011-08-19 09:05:35 +0200209
210 /* bind volumes */
211 struct snd_array bind_ctls;
Kailang Yangdf694da2005-12-05 19:42:22 +0100212};
213
Takashi Iwai1d045db2011-07-07 18:23:21 +0200214#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Takashi Iwai44c02402011-07-08 15:14:19 +0200216static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
217 int dir, unsigned int bits)
218{
219 if (!nid)
220 return false;
221 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
222 if (query_amp_caps(codec, nid, dir) & bits)
223 return true;
224 return false;
225}
226
227#define nid_has_mute(codec, nid, dir) \
228 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
229#define nid_has_volume(codec, nid, dir) \
230 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
231
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232/*
233 * input MUX handling
234 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200235static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
236 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
238 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
239 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200240 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
241 if (mux_idx >= spec->num_mux_defs)
242 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100243 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
244 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200245 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246}
247
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200248static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
249 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250{
251 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
252 struct alc_spec *spec = codec->spec;
253 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
254
255 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
256 return 0;
257}
258
Takashi Iwai21268962011-07-07 15:01:13 +0200259static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260{
Takashi Iwai21268962011-07-07 15:01:13 +0200261 struct alc_spec *spec = codec->spec;
262 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
263
264 if (spec->cur_adc && spec->cur_adc != new_adc) {
265 /* stream is running, let's swap the current ADC */
266 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
267 spec->cur_adc = new_adc;
268 snd_hda_codec_setup_stream(codec, new_adc,
269 spec->cur_adc_stream_tag, 0,
270 spec->cur_adc_format);
271 return true;
272 }
273 return false;
274}
275
276/* select the given imux item; either unmute exclusively or select the route */
277static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
278 unsigned int idx, bool force)
279{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100281 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100282 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200283 int i, type;
284 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Takashi Iwaicd896c32008-11-18 12:36:33 +0100286 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
287 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100288 if (!imux->num_items && mux_idx > 0)
289 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100290
Takashi Iwai21268962011-07-07 15:01:13 +0200291 if (idx >= imux->num_items)
292 idx = imux->num_items - 1;
293 if (spec->cur_mux[adc_idx] == idx && !force)
294 return 0;
295 spec->cur_mux[adc_idx] = idx;
296
297 if (spec->dyn_adc_switch) {
298 alc_dyn_adc_pcm_resetup(codec, idx);
299 adc_idx = spec->dyn_adc_idx[idx];
300 }
301
302 nid = spec->capsrc_nids ?
303 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
304
305 /* no selection? */
306 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
307 return 1;
308
Takashi Iwaia22d5432009-07-27 12:54:26 +0200309 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200310 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100311 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100312 for (i = 0; i < imux->num_items; i++) {
313 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
314 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
315 imux->items[i].index,
316 HDA_AMP_MUTE, v);
317 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100318 } else {
319 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200320 snd_hda_codec_write_cache(codec, nid, 0,
321 AC_VERB_SET_CONNECT_SEL,
322 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100323 }
Takashi Iwai21268962011-07-07 15:01:13 +0200324 return 1;
325}
326
327static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
328 struct snd_ctl_elem_value *ucontrol)
329{
330 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
331 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
332 return alc_mux_select(codec, adc_idx,
333 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100334}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200335
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100337 * set up the input pin config (depending on the given auto-pin type)
338 */
339static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
340 int auto_pin_type)
341{
342 unsigned int val = PIN_IN;
343
Takashi Iwai86e29592010-09-09 14:50:17 +0200344 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100345 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200346 unsigned int oldval;
347 oldval = snd_hda_codec_read(codec, nid, 0,
348 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100349 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100350 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200351 /* if the default pin setup is vref50, we give it priority */
352 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100353 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200354 else if (pincap & AC_PINCAP_VREF_50)
355 val = PIN_VREF50;
356 else if (pincap & AC_PINCAP_VREF_100)
357 val = PIN_VREF100;
358 else if (pincap & AC_PINCAP_VREF_GRD)
359 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100360 }
361 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
362}
363
364/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200365 * Append the given mixer and verb elements for the later use
366 * The mixer array is referred in build_controls(), and init_verbs are
367 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100368 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200369static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100370{
371 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
372 return;
373 spec->mixers[spec->num_mixers++] = mix;
374}
375
376static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
377{
378 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
379 return;
380 spec->init_verbs[spec->num_init_verbs++] = verb;
381}
382
383/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200384 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100385 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200386/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200387static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200388 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
389 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
390 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
391 { }
392};
393
Takashi Iwaia9111322011-05-02 11:30:18 +0200394static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200395 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
396 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
397 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
398 { }
399};
400
Takashi Iwaia9111322011-05-02 11:30:18 +0200401static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200402 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
403 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
404 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
405 { }
406};
407
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200408/*
409 * Fix hardware PLL issue
410 * On some codecs, the analog PLL gating control must be off while
411 * the default value is 1.
412 */
413static void alc_fix_pll(struct hda_codec *codec)
414{
415 struct alc_spec *spec = codec->spec;
416 unsigned int val;
417
418 if (!spec->pll_nid)
419 return;
420 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
421 spec->pll_coef_idx);
422 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
423 AC_VERB_GET_PROC_COEF, 0);
424 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
425 spec->pll_coef_idx);
426 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
427 val & ~(1 << spec->pll_coef_bit));
428}
429
430static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
431 unsigned int coef_idx, unsigned int coef_bit)
432{
433 struct alc_spec *spec = codec->spec;
434 spec->pll_nid = nid;
435 spec->pll_coef_idx = coef_idx;
436 spec->pll_coef_bit = coef_bit;
437 alc_fix_pll(codec);
438}
439
Takashi Iwai1d045db2011-07-07 18:23:21 +0200440/*
441 * Jack-reporting via input-jack layer
442 */
443
444/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200445static int alc_init_jacks(struct hda_codec *codec)
446{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100447#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200448 struct alc_spec *spec = codec->spec;
449 int err;
450 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200451 unsigned int mic_nid = spec->ext_mic_pin;
452 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200453
Takashi Iwai265a0242010-09-21 11:26:21 +0200454 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100455 err = snd_hda_input_jack_add(codec, hp_nid,
456 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200457 if (err < 0)
458 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100459 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200460 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200461
Takashi Iwai265a0242010-09-21 11:26:21 +0200462 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100463 err = snd_hda_input_jack_add(codec, mic_nid,
464 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200465 if (err < 0)
466 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100467 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200468 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200469 if (dock_nid) {
470 err = snd_hda_input_jack_add(codec, dock_nid,
471 SND_JACK_MICROPHONE, NULL);
472 if (err < 0)
473 return err;
474 snd_hda_input_jack_report(codec, dock_nid);
475 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100476#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200477 return 0;
478}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200479
Takashi Iwai1d045db2011-07-07 18:23:21 +0200480/*
481 * Jack detections for HP auto-mute and mic-switch
482 */
483
484/* check each pin in the given array; returns true if any of them is plugged */
485static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200486{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200487 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200488
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200489 for (i = 0; i < num_pins; i++) {
490 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200491 if (!nid)
492 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100493 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200494 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200495 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200496 return present;
497}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200498
Takashi Iwai1d045db2011-07-07 18:23:21 +0200499/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200500static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200501 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200502{
503 struct alc_spec *spec = codec->spec;
504 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200505 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200506 int i;
507
508 for (i = 0; i < num_pins; i++) {
509 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200510 if (!nid)
511 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200512 switch (spec->automute_mode) {
513 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200514 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200515 AC_VERB_SET_PIN_WIDGET_CONTROL,
516 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200517 break;
518 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200519 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200520 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200521 break;
522 case ALC_AUTOMUTE_MIXER:
523 nid = spec->automute_mixer_nid[i];
524 if (!nid)
525 break;
526 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200527 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200528 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200529 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200530 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200531 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200532 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200533}
534
David Henningsson42cf0d02011-09-20 12:04:56 +0200535/* Toggle outputs muting */
536static void update_outputs(struct hda_codec *codec)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200537{
538 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200539 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200540
Takashi Iwaic0a20262011-06-10 15:28:15 +0200541 /* Control HP pins/amps depending on master_mute state;
542 * in general, HP pins/amps control should be enabled in all cases,
543 * but currently set only for master_mute, just to be safe
544 */
545 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
546 spec->autocfg.hp_pins, spec->master_mute, true);
547
David Henningsson42cf0d02011-09-20 12:04:56 +0200548 if (!spec->automute_speaker)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200549 on = 0;
550 else
David Henningsson42cf0d02011-09-20 12:04:56 +0200551 on = spec->hp_jack_present | spec->line_jack_present;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200552 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200553 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200554 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200555
556 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200557 /* if LO is a copy of either HP or Speaker, don't need to handle it */
558 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
559 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200560 return;
David Henningsson42cf0d02011-09-20 12:04:56 +0200561 if (!spec->automute_lo)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200562 on = 0;
563 else
David Henningsson42cf0d02011-09-20 12:04:56 +0200564 on = spec->hp_jack_present;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200565 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200566 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200567 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200568}
569
David Henningsson42cf0d02011-09-20 12:04:56 +0200570static void call_update_outputs(struct hda_codec *codec)
Takashi Iwai24519912011-08-16 15:08:49 +0200571{
572 struct alc_spec *spec = codec->spec;
573 if (spec->automute_hook)
574 spec->automute_hook(codec);
575 else
David Henningsson42cf0d02011-09-20 12:04:56 +0200576 update_outputs(codec);
Takashi Iwai24519912011-08-16 15:08:49 +0200577}
578
Takashi Iwai1d045db2011-07-07 18:23:21 +0200579/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200580static void alc_hp_automute(struct hda_codec *codec)
581{
582 struct alc_spec *spec = codec->spec;
583
David Henningsson42cf0d02011-09-20 12:04:56 +0200584 spec->hp_jack_present =
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200585 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
586 spec->autocfg.hp_pins);
David Henningsson42cf0d02011-09-20 12:04:56 +0200587 if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
Takashi Iwai3c715a92011-08-23 12:41:09 +0200588 return;
David Henningsson42cf0d02011-09-20 12:04:56 +0200589 call_update_outputs(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200590}
591
Takashi Iwai1d045db2011-07-07 18:23:21 +0200592/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200593static void alc_line_automute(struct hda_codec *codec)
594{
595 struct alc_spec *spec = codec->spec;
596
Takashi Iwaie0d32e32011-09-26 15:19:55 +0200597 /* check LO jack only when it's different from HP */
598 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
599 return;
600
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200601 spec->line_jack_present =
602 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
603 spec->autocfg.line_out_pins);
David Henningsson42cf0d02011-09-20 12:04:56 +0200604 if (!spec->automute_speaker || !spec->detect_lo)
Takashi Iwai3c715a92011-08-23 12:41:09 +0200605 return;
David Henningsson42cf0d02011-09-20 12:04:56 +0200606 call_update_outputs(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200607}
608
Takashi Iwai8d087c72011-06-28 12:45:47 +0200609#define get_connection_index(codec, mux, nid) \
610 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200611
Takashi Iwai1d045db2011-07-07 18:23:21 +0200612/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200613static void alc_mic_automute(struct hda_codec *codec)
614{
615 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200616 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200617
Takashi Iwai21268962011-07-07 15:01:13 +0200618 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200619 return;
620 if (snd_BUG_ON(!spec->adc_nids))
621 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200622 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200623 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200624
Takashi Iwai21268962011-07-07 15:01:13 +0200625 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
626 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
627 else if (spec->dock_mic_idx >= 0 &&
628 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
629 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
630 else
631 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200632
Takashi Iwai21268962011-07-07 15:01:13 +0200633 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
634 if (spec->dock_mic_idx >= 0)
635 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200636}
637
Kailang Yangc9b58002007-10-16 14:30:01 +0200638/* unsolicited event for HP jack sensing */
639static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
640{
641 if (codec->vendor_id == 0x10ec0880)
642 res >>= 28;
643 else
644 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200645 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200646 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200647 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200648 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200649 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200650 alc_line_automute(codec);
651 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200652 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200653 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200654 break;
655 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200656}
657
Takashi Iwai1d045db2011-07-07 18:23:21 +0200658/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200659static void alc_inithook(struct hda_codec *codec)
660{
Takashi Iwaid922b512011-04-28 12:18:53 +0200661 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200662 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200663 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200664}
665
Kailang Yangf9423e72008-05-27 12:32:25 +0200666/* additional initialization for ALC888 variants */
667static void alc888_coef_init(struct hda_codec *codec)
668{
669 unsigned int tmp;
670
671 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
672 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
673 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100674 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200675 /* alc888S-VC */
676 snd_hda_codec_read(codec, 0x20, 0,
677 AC_VERB_SET_PROC_COEF, 0x830);
678 else
679 /* alc888-VB */
680 snd_hda_codec_read(codec, 0x20, 0,
681 AC_VERB_SET_PROC_COEF, 0x3030);
682}
683
Takashi Iwai1d045db2011-07-07 18:23:21 +0200684/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200685static void alc889_coef_init(struct hda_codec *codec)
686{
687 unsigned int tmp;
688
689 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
690 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
691 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
692 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
693}
694
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100695/* turn on/off EAPD control (only if available) */
696static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
697{
698 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
699 return;
700 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
701 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
702 on ? 2 : 0);
703}
704
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200705/* turn on/off EAPD controls of the codec */
706static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
707{
708 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200709 static hda_nid_t pins[] = {
710 0x0f, 0x10, 0x14, 0x15, 0
711 };
712 hda_nid_t *p;
713 for (p = pins; *p; p++)
714 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200715}
716
Takashi Iwai1c716152011-04-07 10:37:16 +0200717/* generic shutup callback;
718 * just turning off EPAD and a little pause for avoiding pop-noise
719 */
720static void alc_eapd_shutup(struct hda_codec *codec)
721{
722 alc_auto_setup_eapd(codec, false);
723 msleep(200);
724}
725
Takashi Iwai1d045db2011-07-07 18:23:21 +0200726/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200727static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200728{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200729 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200730
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200731 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200732 switch (type) {
733 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200734 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
735 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200736 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200737 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
738 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200739 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200740 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
741 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200742 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200743 switch (codec->vendor_id) {
744 case 0x10ec0260:
745 snd_hda_codec_write(codec, 0x1a, 0,
746 AC_VERB_SET_COEF_INDEX, 7);
747 tmp = snd_hda_codec_read(codec, 0x1a, 0,
748 AC_VERB_GET_PROC_COEF, 0);
749 snd_hda_codec_write(codec, 0x1a, 0,
750 AC_VERB_SET_COEF_INDEX, 7);
751 snd_hda_codec_write(codec, 0x1a, 0,
752 AC_VERB_SET_PROC_COEF,
753 tmp | 0x2010);
754 break;
755 case 0x10ec0262:
756 case 0x10ec0880:
757 case 0x10ec0882:
758 case 0x10ec0883:
759 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100760 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100761 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200762 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200763 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200764 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200765 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200766 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100767#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200768 case 0x10ec0267:
769 case 0x10ec0268:
770 snd_hda_codec_write(codec, 0x20, 0,
771 AC_VERB_SET_COEF_INDEX, 7);
772 tmp = snd_hda_codec_read(codec, 0x20, 0,
773 AC_VERB_GET_PROC_COEF, 0);
774 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200775 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200776 snd_hda_codec_write(codec, 0x20, 0,
777 AC_VERB_SET_PROC_COEF,
778 tmp | 0x3000);
779 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100780#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200781 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200782 break;
783 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200784}
Kailang Yangea1fb292008-08-26 12:58:38 +0200785
Takashi Iwai1d045db2011-07-07 18:23:21 +0200786/*
787 * Auto-Mute mode mixer enum support
788 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200789static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
790 struct snd_ctl_elem_info *uinfo)
791{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200792 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
793 struct alc_spec *spec = codec->spec;
794 static const char * const texts2[] = {
795 "Disabled", "Enabled"
796 };
797 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200798 "Disabled", "Speaker Only", "Line-Out+Speaker"
799 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200800 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200801
802 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
803 uinfo->count = 1;
David Henningsson42cf0d02011-09-20 12:04:56 +0200804 if (spec->automute_speaker_possible && spec->automute_lo_possible) {
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200805 uinfo->value.enumerated.items = 3;
806 texts = texts3;
807 } else {
808 uinfo->value.enumerated.items = 2;
809 texts = texts2;
810 }
811 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
812 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200813 strcpy(uinfo->value.enumerated.name,
814 texts[uinfo->value.enumerated.item]);
815 return 0;
816}
817
818static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
819 struct snd_ctl_elem_value *ucontrol)
820{
821 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
822 struct alc_spec *spec = codec->spec;
David Henningsson42cf0d02011-09-20 12:04:56 +0200823 unsigned int val = 0;
824 if (spec->automute_speaker)
825 val++;
826 if (spec->automute_lo)
827 val++;
828
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200829 ucontrol->value.enumerated.item[0] = val;
830 return 0;
831}
832
833static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
834 struct snd_ctl_elem_value *ucontrol)
835{
836 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
837 struct alc_spec *spec = codec->spec;
838
839 switch (ucontrol->value.enumerated.item[0]) {
840 case 0:
David Henningsson42cf0d02011-09-20 12:04:56 +0200841 if (!spec->automute_speaker && !spec->automute_lo)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200842 return 0;
David Henningsson42cf0d02011-09-20 12:04:56 +0200843 spec->automute_speaker = 0;
844 spec->automute_lo = 0;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200845 break;
846 case 1:
David Henningsson42cf0d02011-09-20 12:04:56 +0200847 if (spec->automute_speaker_possible) {
848 if (!spec->automute_lo && spec->automute_speaker)
849 return 0;
850 spec->automute_speaker = 1;
851 spec->automute_lo = 0;
852 } else if (spec->automute_lo_possible) {
853 if (spec->automute_lo)
854 return 0;
855 spec->automute_lo = 1;
856 } else
857 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200858 break;
859 case 2:
David Henningsson42cf0d02011-09-20 12:04:56 +0200860 if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200861 return -EINVAL;
David Henningsson42cf0d02011-09-20 12:04:56 +0200862 if (spec->automute_speaker && spec->automute_lo)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200863 return 0;
David Henningsson42cf0d02011-09-20 12:04:56 +0200864 spec->automute_speaker = 1;
865 spec->automute_lo = 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200866 break;
867 default:
868 return -EINVAL;
869 }
David Henningsson42cf0d02011-09-20 12:04:56 +0200870 call_update_outputs(codec);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200871 return 1;
872}
873
Takashi Iwaia9111322011-05-02 11:30:18 +0200874static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200875 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
876 .name = "Auto-Mute Mode",
877 .info = alc_automute_mode_info,
878 .get = alc_automute_mode_get,
879 .put = alc_automute_mode_put,
880};
881
Takashi Iwai1d045db2011-07-07 18:23:21 +0200882static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
883{
884 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
885 return snd_array_new(&spec->kctls);
886}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200887
888static int alc_add_automute_mode_enum(struct hda_codec *codec)
889{
890 struct alc_spec *spec = codec->spec;
891 struct snd_kcontrol_new *knew;
892
893 knew = alc_kcontrol_new(spec);
894 if (!knew)
895 return -ENOMEM;
896 *knew = alc_automute_mode_enum;
897 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
898 if (!knew->name)
899 return -ENOMEM;
900 return 0;
901}
902
Takashi Iwai1d045db2011-07-07 18:23:21 +0200903/*
904 * Check the availability of HP/line-out auto-mute;
905 * Set up appropriately if really supported
906 */
David Henningsson42cf0d02011-09-20 12:04:56 +0200907static void alc_init_automute(struct hda_codec *codec)
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200908{
909 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200910 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200911 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200912 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200913
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200914 if (cfg->hp_pins[0])
915 present++;
916 if (cfg->line_out_pins[0])
917 present++;
918 if (cfg->speaker_pins[0])
919 present++;
920 if (present < 2) /* need two different output types */
921 return;
Kailang Yangc9b58002007-10-16 14:30:01 +0200922
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200923 if (!cfg->speaker_pins[0] &&
924 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200925 memcpy(cfg->speaker_pins, cfg->line_out_pins,
926 sizeof(cfg->speaker_pins));
927 cfg->speaker_outs = cfg->line_outs;
928 }
929
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200930 if (!cfg->hp_pins[0] &&
931 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200932 memcpy(cfg->hp_pins, cfg->line_out_pins,
933 sizeof(cfg->hp_pins));
934 cfg->hp_outs = cfg->line_outs;
935 }
936
David Henningsson42cf0d02011-09-20 12:04:56 +0200937 spec->automute_mode = ALC_AUTOMUTE_PIN;
938
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200939 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200940 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200941 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200942 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200943 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200944 nid);
945 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200946 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200947 AC_USRSP_EN | ALC_HP_EVENT);
David Henningsson42cf0d02011-09-20 12:04:56 +0200948 spec->detect_hp = 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200949 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200950
David Henningsson42cf0d02011-09-20 12:04:56 +0200951 if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
952 if (cfg->speaker_outs)
953 for (i = 0; i < cfg->line_outs; i++) {
954 hda_nid_t nid = cfg->line_out_pins[i];
955 if (!is_jack_detectable(codec, nid))
956 continue;
957 snd_printdd("realtek: Enable Line-Out "
958 "auto-muting on NID 0x%x\n", nid);
959 snd_hda_codec_write_cache(codec, nid, 0,
960 AC_VERB_SET_UNSOLICITED_ENABLE,
961 AC_USRSP_EN | ALC_FRONT_EVENT);
962 spec->detect_lo = 1;
963 }
964 spec->automute_lo_possible = spec->detect_hp;
965 }
966
967 spec->automute_speaker_possible = cfg->speaker_outs &&
968 (spec->detect_hp || spec->detect_lo);
969
970 spec->automute_lo = spec->automute_lo_possible;
971 spec->automute_speaker = spec->automute_speaker_possible;
972
973 if (spec->automute_speaker_possible || spec->automute_lo_possible) {
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200974 /* create a control for automute mode */
975 alc_add_automute_mode_enum(codec);
976 spec->unsol_event = alc_sku_unsol_event;
977 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200978}
979
Takashi Iwai1d045db2011-07-07 18:23:21 +0200980/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200981static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
982{
983 int i;
984 for (i = 0; i < nums; i++)
985 if (list[i] == nid)
986 return i;
987 return -1;
988}
989
Takashi Iwai1d045db2011-07-07 18:23:21 +0200990/* check whether dynamic ADC-switching is available */
991static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
992{
993 struct alc_spec *spec = codec->spec;
994 struct hda_input_mux *imux = &spec->private_imux[0];
995 int i, n, idx;
996 hda_nid_t cap, pin;
997
998 if (imux != spec->input_mux) /* no dynamic imux? */
999 return false;
1000
1001 for (n = 0; n < spec->num_adc_nids; n++) {
1002 cap = spec->private_capsrc_nids[n];
1003 for (i = 0; i < imux->num_items; i++) {
1004 pin = spec->imux_pins[i];
1005 if (!pin)
1006 return false;
1007 if (get_connection_index(codec, cap, pin) < 0)
1008 break;
1009 }
1010 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +02001011 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001012 }
1013
1014 for (i = 0; i < imux->num_items; i++) {
1015 pin = spec->imux_pins[i];
1016 for (n = 0; n < spec->num_adc_nids; n++) {
1017 cap = spec->private_capsrc_nids[n];
1018 idx = get_connection_index(codec, cap, pin);
1019 if (idx >= 0) {
1020 imux->items[i].index = idx;
1021 spec->dyn_adc_idx[i] = n;
1022 break;
1023 }
1024 }
1025 }
1026
1027 snd_printdd("realtek: enabling ADC switching\n");
1028 spec->dyn_adc_switch = 1;
1029 return true;
1030}
Takashi Iwai21268962011-07-07 15:01:13 +02001031
1032/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1033static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1034{
1035 struct alc_spec *spec = codec->spec;
1036 struct hda_input_mux *imux;
1037 static char * const texts[3] = {
1038 "Mic", "Internal Mic", "Dock Mic"
1039 };
1040 int i;
1041
1042 if (!spec->auto_mic)
1043 return false;
1044 imux = &spec->private_imux[0];
1045 if (spec->input_mux == imux)
1046 return true;
1047 spec->imux_pins[0] = spec->ext_mic_pin;
1048 spec->imux_pins[1] = spec->int_mic_pin;
1049 spec->imux_pins[2] = spec->dock_mic_pin;
1050 for (i = 0; i < 3; i++) {
1051 strcpy(imux->items[i].label, texts[i]);
1052 if (spec->imux_pins[i])
1053 imux->num_items = i + 1;
1054 }
1055 spec->num_mux_defs = 1;
1056 spec->input_mux = imux;
1057 return true;
1058}
1059
1060/* check whether all auto-mic pins are valid; setup indices if OK */
1061static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1062{
1063 struct alc_spec *spec = codec->spec;
1064 const struct hda_input_mux *imux;
1065
1066 if (!spec->auto_mic)
1067 return false;
1068 if (spec->auto_mic_valid_imux)
1069 return true; /* already checked */
1070
1071 /* fill up imux indices */
1072 if (!alc_check_dyn_adc_switch(codec)) {
1073 spec->auto_mic = 0;
1074 return false;
1075 }
1076
1077 imux = spec->input_mux;
1078 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1079 spec->imux_pins, imux->num_items);
1080 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1081 spec->imux_pins, imux->num_items);
1082 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1083 spec->imux_pins, imux->num_items);
1084 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1085 spec->auto_mic = 0;
1086 return false; /* no corresponding imux */
1087 }
1088
1089 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1090 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001091 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001092 if (spec->dock_mic_pin)
1093 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1094 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001095 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001096
1097 spec->auto_mic_valid_imux = 1;
1098 spec->auto_mic = 1;
1099 return true;
1100}
1101
Takashi Iwai1d045db2011-07-07 18:23:21 +02001102/*
1103 * Check the availability of auto-mic switch;
1104 * Set up if really supported
1105 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001106static void alc_init_auto_mic(struct hda_codec *codec)
1107{
1108 struct alc_spec *spec = codec->spec;
1109 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001110 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001111 int i;
1112
Takashi Iwai21268962011-07-07 15:01:13 +02001113 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1114
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001115 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001116 for (i = 0; i < cfg->num_inputs; i++) {
1117 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001118 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001119 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001120 switch (snd_hda_get_input_pin_attr(defcfg)) {
1121 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001122 if (fixed)
1123 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001124 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1125 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001126 fixed = nid;
1127 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001128 case INPUT_PIN_ATTR_UNUSED:
1129 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001130 case INPUT_PIN_ATTR_DOCK:
1131 if (dock)
1132 return; /* already occupied */
1133 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1134 return; /* invalid type */
1135 dock = nid;
1136 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001137 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001138 if (ext)
1139 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001140 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1141 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001142 ext = nid;
1143 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001144 }
1145 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001146 if (!ext && dock) {
1147 ext = dock;
1148 dock = 0;
1149 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001150 if (!ext || !fixed)
1151 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001152 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001153 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001154 if (dock && !is_jack_detectable(codec, dock))
1155 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001156
1157 /* check imux indices */
1158 spec->ext_mic_pin = ext;
1159 spec->int_mic_pin = fixed;
1160 spec->dock_mic_pin = dock;
1161
1162 spec->auto_mic = 1;
1163 if (!alc_auto_mic_check_imux(codec))
1164 return;
1165
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001166 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1167 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001168 spec->unsol_event = alc_sku_unsol_event;
1169}
1170
Takashi Iwai1d045db2011-07-07 18:23:21 +02001171/* check the availabilities of auto-mute and auto-mic switches */
1172static void alc_auto_check_switches(struct hda_codec *codec)
1173{
David Henningsson42cf0d02011-09-20 12:04:56 +02001174 alc_init_automute(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001175 alc_init_auto_mic(codec);
1176}
1177
1178/*
1179 * Realtek SSID verification
1180 */
1181
David Henningsson90622912010-10-14 14:50:18 +02001182/* Could be any non-zero and even value. When used as fixup, tells
1183 * the driver to ignore any present sku defines.
1184 */
1185#define ALC_FIXUP_SKU_IGNORE (2)
1186
Kailang Yangda00c242010-03-19 11:23:45 +01001187static int alc_auto_parse_customize_define(struct hda_codec *codec)
1188{
1189 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001190 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001191 struct alc_spec *spec = codec->spec;
1192
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001193 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1194
David Henningsson90622912010-10-14 14:50:18 +02001195 if (spec->cdefine.fixup) {
1196 ass = spec->cdefine.sku_cfg;
1197 if (ass == ALC_FIXUP_SKU_IGNORE)
1198 return -1;
1199 goto do_sku;
1200 }
1201
Kailang Yangda00c242010-03-19 11:23:45 +01001202 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001203 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001204 goto do_sku;
1205
1206 nid = 0x1d;
1207 if (codec->vendor_id == 0x10ec0260)
1208 nid = 0x17;
1209 ass = snd_hda_codec_get_pincfg(codec, nid);
1210
1211 if (!(ass & 1)) {
1212 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1213 codec->chip_name, ass);
1214 return -1;
1215 }
1216
1217 /* check sum */
1218 tmp = 0;
1219 for (i = 1; i < 16; i++) {
1220 if ((ass >> i) & 1)
1221 tmp++;
1222 }
1223 if (((ass >> 16) & 0xf) != tmp)
1224 return -1;
1225
1226 spec->cdefine.port_connectivity = ass >> 30;
1227 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1228 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1229 spec->cdefine.customization = ass >> 8;
1230do_sku:
1231 spec->cdefine.sku_cfg = ass;
1232 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1233 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1234 spec->cdefine.swap = (ass & 0x2) >> 1;
1235 spec->cdefine.override = ass & 0x1;
1236
1237 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1238 nid, spec->cdefine.sku_cfg);
1239 snd_printd("SKU: port_connectivity=0x%x\n",
1240 spec->cdefine.port_connectivity);
1241 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1242 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1243 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1244 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1245 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1246 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1247 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1248
1249 return 0;
1250}
1251
Takashi Iwai1d045db2011-07-07 18:23:21 +02001252/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001253static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1254{
Takashi Iwai21268962011-07-07 15:01:13 +02001255 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001256}
1257
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001258/* check subsystem ID and set up device-specific initialization;
1259 * return 1 if initialized, 0 if invalid SSID
1260 */
1261/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1262 * 31 ~ 16 : Manufacture ID
1263 * 15 ~ 8 : SKU ID
1264 * 7 ~ 0 : Assembly ID
1265 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1266 */
1267static int alc_subsystem_id(struct hda_codec *codec,
1268 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001269 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001270{
1271 unsigned int ass, tmp, i;
1272 unsigned nid;
1273 struct alc_spec *spec = codec->spec;
1274
David Henningsson90622912010-10-14 14:50:18 +02001275 if (spec->cdefine.fixup) {
1276 ass = spec->cdefine.sku_cfg;
1277 if (ass == ALC_FIXUP_SKU_IGNORE)
1278 return 0;
1279 goto do_sku;
1280 }
1281
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001282 ass = codec->subsystem_id & 0xffff;
1283 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1284 goto do_sku;
1285
1286 /* invalid SSID, check the special NID pin defcfg instead */
1287 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001288 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001289 * 29~21 : reserve
1290 * 20 : PCBEEP input
1291 * 19~16 : Check sum (15:1)
1292 * 15~1 : Custom
1293 * 0 : override
1294 */
1295 nid = 0x1d;
1296 if (codec->vendor_id == 0x10ec0260)
1297 nid = 0x17;
1298 ass = snd_hda_codec_get_pincfg(codec, nid);
1299 snd_printd("realtek: No valid SSID, "
1300 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001301 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001302 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001303 return 0;
1304 if ((ass >> 30) != 1) /* no physical connection */
1305 return 0;
1306
1307 /* check sum */
1308 tmp = 0;
1309 for (i = 1; i < 16; i++) {
1310 if ((ass >> i) & 1)
1311 tmp++;
1312 }
1313 if (((ass >> 16) & 0xf) != tmp)
1314 return 0;
1315do_sku:
1316 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1317 ass & 0xffff, codec->vendor_id);
1318 /*
1319 * 0 : override
1320 * 1 : Swap Jack
1321 * 2 : 0 --> Desktop, 1 --> Laptop
1322 * 3~5 : External Amplifier control
1323 * 7~6 : Reserved
1324 */
1325 tmp = (ass & 0x38) >> 3; /* external Amp control */
1326 switch (tmp) {
1327 case 1:
1328 spec->init_amp = ALC_INIT_GPIO1;
1329 break;
1330 case 3:
1331 spec->init_amp = ALC_INIT_GPIO2;
1332 break;
1333 case 7:
1334 spec->init_amp = ALC_INIT_GPIO3;
1335 break;
1336 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001337 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001338 spec->init_amp = ALC_INIT_DEFAULT;
1339 break;
1340 }
1341
1342 /* is laptop or Desktop and enable the function "Mute internal speaker
1343 * when the external headphone out jack is plugged"
1344 */
1345 if (!(ass & 0x8000))
1346 return 1;
1347 /*
1348 * 10~8 : Jack location
1349 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1350 * 14~13: Resvered
1351 * 15 : 1 --> enable the function "Mute internal speaker
1352 * when the external headphone out jack is plugged"
1353 */
Takashi Iwai5fe6e012011-09-26 10:41:21 +02001354 if (!spec->autocfg.hp_pins[0] &&
1355 !(spec->autocfg.line_out_pins[0] &&
1356 spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001357 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001358 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1359 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001360 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001361 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001362 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001363 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001364 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001365 else if (tmp == 3)
1366 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001367 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001368 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001369 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1370 spec->autocfg.line_outs))
1371 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001372 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001373 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001374 return 1;
1375}
Kailang Yangea1fb292008-08-26 12:58:38 +02001376
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001377/* Check the validity of ALC subsystem-id
1378 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1379static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001380{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001381 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001382 struct alc_spec *spec = codec->spec;
1383 snd_printd("realtek: "
1384 "Enable default setup for auto mode as fallback\n");
1385 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001386 }
Takashi Iwai21268962011-07-07 15:01:13 +02001387}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001388
Takashi Iwai41e41f12005-06-08 14:48:49 +02001389/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001390 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001391 */
1392
1393struct alc_pincfg {
1394 hda_nid_t nid;
1395 u32 val;
1396};
1397
Todd Broche1eb5f12010-12-06 11:19:51 -08001398struct alc_model_fixup {
1399 const int id;
1400 const char *name;
1401};
1402
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001403struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001404 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001405 bool chained;
1406 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001407 union {
1408 unsigned int sku;
1409 const struct alc_pincfg *pins;
1410 const struct hda_verb *verbs;
1411 void (*func)(struct hda_codec *codec,
1412 const struct alc_fixup *fix,
1413 int action);
1414 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001415};
1416
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001417enum {
1418 ALC_FIXUP_INVALID,
1419 ALC_FIXUP_SKU,
1420 ALC_FIXUP_PINS,
1421 ALC_FIXUP_VERBS,
1422 ALC_FIXUP_FUNC,
1423};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001424
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001425enum {
1426 ALC_FIXUP_ACT_PRE_PROBE,
1427 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001428 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001429};
1430
1431static void alc_apply_fixup(struct hda_codec *codec, int action)
1432{
1433 struct alc_spec *spec = codec->spec;
1434 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001435#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001436 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001437#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001438 int depth = 0;
1439
1440 if (!spec->fixup_list)
1441 return;
1442
1443 while (id >= 0) {
1444 const struct alc_fixup *fix = spec->fixup_list + id;
1445 const struct alc_pincfg *cfg;
1446
1447 switch (fix->type) {
1448 case ALC_FIXUP_SKU:
1449 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1450 break;;
1451 snd_printdd(KERN_INFO "hda_codec: %s: "
1452 "Apply sku override for %s\n",
1453 codec->chip_name, modelname);
1454 spec->cdefine.sku_cfg = fix->v.sku;
1455 spec->cdefine.fixup = 1;
1456 break;
1457 case ALC_FIXUP_PINS:
1458 cfg = fix->v.pins;
1459 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1460 break;
1461 snd_printdd(KERN_INFO "hda_codec: %s: "
1462 "Apply pincfg for %s\n",
1463 codec->chip_name, modelname);
1464 for (; cfg->nid; cfg++)
1465 snd_hda_codec_set_pincfg(codec, cfg->nid,
1466 cfg->val);
1467 break;
1468 case ALC_FIXUP_VERBS:
1469 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1470 break;
1471 snd_printdd(KERN_INFO "hda_codec: %s: "
1472 "Apply fix-verbs for %s\n",
1473 codec->chip_name, modelname);
1474 add_verb(codec->spec, fix->v.verbs);
1475 break;
1476 case ALC_FIXUP_FUNC:
1477 if (!fix->v.func)
1478 break;
1479 snd_printdd(KERN_INFO "hda_codec: %s: "
1480 "Apply fix-func for %s\n",
1481 codec->chip_name, modelname);
1482 fix->v.func(codec, fix, action);
1483 break;
1484 default:
1485 snd_printk(KERN_ERR "hda_codec: %s: "
1486 "Invalid fixup type %d\n",
1487 codec->chip_name, fix->type);
1488 break;
1489 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001490 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001491 break;
1492 if (++depth > 10)
1493 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001494 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001495 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001496}
1497
Todd Broche1eb5f12010-12-06 11:19:51 -08001498static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001499 const struct alc_model_fixup *models,
1500 const struct snd_pci_quirk *quirk,
1501 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001502{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001503 struct alc_spec *spec = codec->spec;
1504 int id = -1;
1505 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001506
Todd Broche1eb5f12010-12-06 11:19:51 -08001507 if (codec->modelname && models) {
1508 while (models->name) {
1509 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001510 id = models->id;
1511 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001512 break;
1513 }
1514 models++;
1515 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001516 }
1517 if (id < 0) {
1518 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1519 if (quirk) {
1520 id = quirk->value;
1521#ifdef CONFIG_SND_DEBUG_VERBOSE
1522 name = quirk->name;
1523#endif
1524 }
1525 }
1526
1527 spec->fixup_id = id;
1528 if (id >= 0) {
1529 spec->fixup_list = fixlist;
1530 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001531 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001532}
1533
Takashi Iwai1d045db2011-07-07 18:23:21 +02001534/*
1535 * COEF access helper functions
1536 */
Kailang Yang274693f2009-12-03 10:07:50 +01001537static int alc_read_coef_idx(struct hda_codec *codec,
1538 unsigned int coef_idx)
1539{
1540 unsigned int val;
1541 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1542 coef_idx);
1543 val = snd_hda_codec_read(codec, 0x20, 0,
1544 AC_VERB_GET_PROC_COEF, 0);
1545 return val;
1546}
1547
Kailang Yang977ddd62010-09-15 10:02:29 +02001548static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1549 unsigned int coef_val)
1550{
1551 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1552 coef_idx);
1553 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1554 coef_val);
1555}
1556
Takashi Iwai1d045db2011-07-07 18:23:21 +02001557/*
1558 * Digital I/O handling
1559 */
1560
Takashi Iwai757899a2010-07-30 10:48:14 +02001561/* set right pin controls for digital I/O */
1562static void alc_auto_init_digital(struct hda_codec *codec)
1563{
1564 struct alc_spec *spec = codec->spec;
1565 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001566 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001567
1568 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1569 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001570 if (!pin)
1571 continue;
1572 snd_hda_codec_write(codec, pin, 0,
1573 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1574 if (!i)
1575 dac = spec->multiout.dig_out_nid;
1576 else
1577 dac = spec->slave_dig_outs[i - 1];
1578 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1579 continue;
1580 snd_hda_codec_write(codec, dac, 0,
1581 AC_VERB_SET_AMP_GAIN_MUTE,
1582 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001583 }
1584 pin = spec->autocfg.dig_in_pin;
1585 if (pin)
1586 snd_hda_codec_write(codec, pin, 0,
1587 AC_VERB_SET_PIN_WIDGET_CONTROL,
1588 PIN_IN);
1589}
1590
1591/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1592static void alc_auto_parse_digital(struct hda_codec *codec)
1593{
1594 struct alc_spec *spec = codec->spec;
1595 int i, err;
1596 hda_nid_t dig_nid;
1597
1598 /* support multiple SPDIFs; the secondary is set up as a slave */
1599 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001600 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001601 err = snd_hda_get_connections(codec,
1602 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001603 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001604 if (err < 0)
1605 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001606 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001607 if (!i) {
1608 spec->multiout.dig_out_nid = dig_nid;
1609 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1610 } else {
1611 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1612 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1613 break;
1614 spec->slave_dig_outs[i - 1] = dig_nid;
1615 }
1616 }
1617
1618 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001619 dig_nid = codec->start_nid;
1620 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1621 unsigned int wcaps = get_wcaps(codec, dig_nid);
1622 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1623 continue;
1624 if (!(wcaps & AC_WCAP_DIGITAL))
1625 continue;
1626 if (!(wcaps & AC_WCAP_CONN_LIST))
1627 continue;
1628 err = get_connection_index(codec, dig_nid,
1629 spec->autocfg.dig_in_pin);
1630 if (err >= 0) {
1631 spec->dig_in_nid = dig_nid;
1632 break;
1633 }
1634 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001635 }
1636}
1637
Takashi Iwaif95474e2007-07-10 00:47:43 +02001638/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001639 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001640 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001641static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1642 struct snd_ctl_elem_info *uinfo)
1643{
1644 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1645 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001646 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001647 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001648
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001649 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001650 if (spec->vol_in_capsrc)
1651 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1652 else
1653 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1654 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001655 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001656 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001657 return err;
1658}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001660static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1661 unsigned int size, unsigned int __user *tlv)
1662{
1663 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1664 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001665 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001666 int err;
1667
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001668 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001669 if (spec->vol_in_capsrc)
1670 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1671 else
1672 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1673 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001674 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001675 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001676 return err;
1677}
1678
1679typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1680 struct snd_ctl_elem_value *ucontrol);
1681
1682static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1683 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001684 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001685{
1686 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1687 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001688 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001689
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001690 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001691 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001692 for (i = 0; i < spec->num_adc_nids; i++) {
1693 kcontrol->private_value =
1694 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1695 3, 0, HDA_INPUT);
1696 err = func(kcontrol, ucontrol);
1697 if (err < 0)
1698 goto error;
1699 }
1700 } else {
1701 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001702 if (spec->vol_in_capsrc)
1703 kcontrol->private_value =
1704 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1705 3, 0, HDA_OUTPUT);
1706 else
1707 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001708 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1709 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001710 err = func(kcontrol, ucontrol);
1711 }
1712 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001713 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001714 return err;
1715}
1716
1717static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1718 struct snd_ctl_elem_value *ucontrol)
1719{
1720 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001721 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001722}
1723
1724static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1725 struct snd_ctl_elem_value *ucontrol)
1726{
1727 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001728 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001729}
1730
1731/* capture mixer elements */
1732#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1733
1734static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1735 struct snd_ctl_elem_value *ucontrol)
1736{
1737 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001738 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001739}
1740
1741static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1742 struct snd_ctl_elem_value *ucontrol)
1743{
1744 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001745 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001746}
1747
Takashi Iwaia23b6882009-03-23 15:21:36 +01001748#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001749 { \
1750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1751 .name = "Capture Switch", \
1752 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1753 .count = num, \
1754 .info = alc_cap_sw_info, \
1755 .get = alc_cap_sw_get, \
1756 .put = alc_cap_sw_put, \
1757 }, \
1758 { \
1759 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1760 .name = "Capture Volume", \
1761 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1762 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1763 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1764 .count = num, \
1765 .info = alc_cap_vol_info, \
1766 .get = alc_cap_vol_get, \
1767 .put = alc_cap_vol_put, \
1768 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001769 }
1770
1771#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001772 { \
1773 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1774 /* .name = "Capture Source", */ \
1775 .name = "Input Source", \
1776 .count = num, \
1777 .info = alc_mux_enum_info, \
1778 .get = alc_mux_enum_get, \
1779 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001780 }
1781
1782#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001783static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001784 _DEFINE_CAPMIX(num), \
1785 _DEFINE_CAPSRC(num), \
1786 { } /* end */ \
1787}
1788
1789#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001790static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001791 _DEFINE_CAPMIX(num), \
1792 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001793}
1794
1795/* up to three ADCs */
1796DEFINE_CAPMIX(1);
1797DEFINE_CAPMIX(2);
1798DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001799DEFINE_CAPMIX_NOSRC(1);
1800DEFINE_CAPMIX_NOSRC(2);
1801DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001802
1803/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001804 * virtual master controls
1805 */
1806
1807/*
1808 * slave controls for virtual master
1809 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001810static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001811 "Front Playback Volume",
1812 "Surround Playback Volume",
1813 "Center Playback Volume",
1814 "LFE Playback Volume",
1815 "Side Playback Volume",
1816 "Headphone Playback Volume",
1817 "Speaker Playback Volume",
1818 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001819 "Line-Out Playback Volume",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001820 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001821 NULL,
1822};
1823
Takashi Iwaiea734962011-01-17 11:29:34 +01001824static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001825 "Front Playback Switch",
1826 "Surround Playback Switch",
1827 "Center Playback Switch",
1828 "LFE Playback Switch",
1829 "Side Playback Switch",
1830 "Headphone Playback Switch",
1831 "Speaker Playback Switch",
1832 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001833 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001834 "Line-Out Playback Switch",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001835 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001836 NULL,
1837};
1838
1839/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001840 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001842
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001843#define NID_MAPPING (-1)
1844
1845#define SUBDEV_SPEAKER_ (0 << 6)
1846#define SUBDEV_HP_ (1 << 6)
1847#define SUBDEV_LINE_ (2 << 6)
1848#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1849#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1850#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1851
Takashi Iwai603c4012008-07-30 15:01:44 +02001852static void alc_free_kctls(struct hda_codec *codec);
1853
Takashi Iwai67d634c2009-11-16 15:35:59 +01001854#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001855/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001856static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001857 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001858 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001859 { } /* end */
1860};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001861#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001862
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863static int alc_build_controls(struct hda_codec *codec)
1864{
1865 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001866 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001867 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001868 int i, j, err;
1869 unsigned int u;
1870 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
1872 for (i = 0; i < spec->num_mixers; i++) {
1873 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1874 if (err < 0)
1875 return err;
1876 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001877 if (spec->cap_mixer) {
1878 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1879 if (err < 0)
1880 return err;
1881 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001883 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001884 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001885 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 if (err < 0)
1887 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001888 if (!spec->no_analog) {
1889 err = snd_hda_create_spdif_share_sw(codec,
1890 &spec->multiout);
1891 if (err < 0)
1892 return err;
1893 spec->multiout.share_spdif = 1;
1894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 }
1896 if (spec->dig_in_nid) {
1897 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1898 if (err < 0)
1899 return err;
1900 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001901
Takashi Iwai67d634c2009-11-16 15:35:59 +01001902#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001903 /* create beep controls if needed */
1904 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001905 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001906 for (knew = alc_beep_mixer; knew->name; knew++) {
1907 struct snd_kcontrol *kctl;
1908 kctl = snd_ctl_new1(knew, codec);
1909 if (!kctl)
1910 return -ENOMEM;
1911 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001912 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001913 if (err < 0)
1914 return err;
1915 }
1916 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001917#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001918
Takashi Iwai2134ea42008-01-10 16:53:55 +01001919 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001920 if (!spec->no_analog &&
1921 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001922 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001923 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001924 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001925 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001926 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001927 if (err < 0)
1928 return err;
1929 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001930 if (!spec->no_analog &&
1931 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001932 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1933 NULL, alc_slave_sws);
1934 if (err < 0)
1935 return err;
1936 }
1937
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001938 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001939 if (spec->capsrc_nids || spec->adc_nids) {
1940 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1941 if (!kctl)
1942 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1943 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001944 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001945 if (!nids)
1946 nids = spec->adc_nids;
1947 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1948 if (err < 0)
1949 return err;
1950 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001951 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001952 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001953 const char *kname = kctl ? kctl->id.name : NULL;
1954 for (knew = spec->cap_mixer; knew->name; knew++) {
1955 if (kname && strcmp(knew->name, kname) == 0)
1956 continue;
1957 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1958 for (i = 0; kctl && i < kctl->count; i++) {
1959 err = snd_hda_add_nid(codec, kctl, i,
1960 spec->adc_nids[i]);
1961 if (err < 0)
1962 return err;
1963 }
1964 }
1965 }
1966
1967 /* other nid->control mapping */
1968 for (i = 0; i < spec->num_mixers; i++) {
1969 for (knew = spec->mixers[i]; knew->name; knew++) {
1970 if (knew->iface != NID_MAPPING)
1971 continue;
1972 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1973 if (kctl == NULL)
1974 continue;
1975 u = knew->subdevice;
1976 for (j = 0; j < 4; j++, u >>= 8) {
1977 nid = u & 0x3f;
1978 if (nid == 0)
1979 continue;
1980 switch (u & 0xc0) {
1981 case SUBDEV_SPEAKER_:
1982 nid = spec->autocfg.speaker_pins[nid];
1983 break;
1984 case SUBDEV_LINE_:
1985 nid = spec->autocfg.line_out_pins[nid];
1986 break;
1987 case SUBDEV_HP_:
1988 nid = spec->autocfg.hp_pins[nid];
1989 break;
1990 default:
1991 continue;
1992 }
1993 err = snd_hda_add_nid(codec, kctl, 0, nid);
1994 if (err < 0)
1995 return err;
1996 }
1997 u = knew->private_value;
1998 for (j = 0; j < 4; j++, u >>= 8) {
1999 nid = u & 0xff;
2000 if (nid == 0)
2001 continue;
2002 err = snd_hda_add_nid(codec, kctl, 0, nid);
2003 if (err < 0)
2004 return err;
2005 }
2006 }
2007 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01002008
2009 alc_free_kctls(codec); /* no longer needed */
2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 return 0;
2012}
2013
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002014
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002016 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002017 */
Takashi Iwai16ded522005-06-10 19:58:24 +02002018
Takashi Iwai584c0c42011-03-10 12:51:11 +01002019static void alc_init_special_input_src(struct hda_codec *codec);
2020
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021static int alc_init(struct hda_codec *codec)
2022{
2023 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002024 unsigned int i;
2025
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002026 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02002027 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002028
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002029 for (i = 0; i < spec->num_init_verbs; i++)
2030 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01002031 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002032
2033 if (spec->init_hook)
2034 spec->init_hook(codec);
2035
Takashi Iwai58701122011-01-13 15:41:45 +01002036 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2037
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002038 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 return 0;
2040}
2041
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002042static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2043{
2044 struct alc_spec *spec = codec->spec;
2045
2046 if (spec->unsol_event)
2047 spec->unsol_event(codec, res);
2048}
2049
Takashi Iwaicb53c622007-08-10 17:21:45 +02002050#ifdef CONFIG_SND_HDA_POWER_SAVE
2051static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2052{
2053 struct alc_spec *spec = codec->spec;
2054 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2055}
2056#endif
2057
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058/*
2059 * Analog playback callbacks
2060 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002061static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002063 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064{
2065 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002066 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2067 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068}
2069
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002070static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 struct hda_codec *codec,
2072 unsigned int stream_tag,
2073 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002074 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075{
2076 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002077 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2078 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079}
2080
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002081static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002083 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084{
2085 struct alc_spec *spec = codec->spec;
2086 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2087}
2088
2089/*
2090 * Digital out
2091 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002092static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002094 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095{
2096 struct alc_spec *spec = codec->spec;
2097 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2098}
2099
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002100static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002101 struct hda_codec *codec,
2102 unsigned int stream_tag,
2103 unsigned int format,
2104 struct snd_pcm_substream *substream)
2105{
2106 struct alc_spec *spec = codec->spec;
2107 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2108 stream_tag, format, substream);
2109}
2110
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002111static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002112 struct hda_codec *codec,
2113 struct snd_pcm_substream *substream)
2114{
2115 struct alc_spec *spec = codec->spec;
2116 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2117}
2118
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002119static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002121 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122{
2123 struct alc_spec *spec = codec->spec;
2124 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2125}
2126
2127/*
2128 * Analog capture
2129 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002130static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 struct hda_codec *codec,
2132 unsigned int stream_tag,
2133 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002134 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135{
2136 struct alc_spec *spec = codec->spec;
2137
Takashi Iwai63300792008-01-24 15:31:36 +01002138 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 stream_tag, 0, format);
2140 return 0;
2141}
2142
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002143static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002145 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146{
2147 struct alc_spec *spec = codec->spec;
2148
Takashi Iwai888afa12008-03-18 09:57:50 +01002149 snd_hda_codec_cleanup_stream(codec,
2150 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 return 0;
2152}
2153
Takashi Iwai840b64c2010-07-13 22:49:01 +02002154/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002155static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002156 struct hda_codec *codec,
2157 unsigned int stream_tag,
2158 unsigned int format,
2159 struct snd_pcm_substream *substream)
2160{
2161 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002162 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002163 spec->cur_adc_stream_tag = stream_tag;
2164 spec->cur_adc_format = format;
2165 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2166 return 0;
2167}
2168
Takashi Iwai21268962011-07-07 15:01:13 +02002169static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002170 struct hda_codec *codec,
2171 struct snd_pcm_substream *substream)
2172{
2173 struct alc_spec *spec = codec->spec;
2174 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2175 spec->cur_adc = 0;
2176 return 0;
2177}
2178
Takashi Iwai21268962011-07-07 15:01:13 +02002179static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002180 .substreams = 1,
2181 .channels_min = 2,
2182 .channels_max = 2,
2183 .nid = 0, /* fill later */
2184 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002185 .prepare = dyn_adc_capture_pcm_prepare,
2186 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002187 },
2188};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
2190/*
2191 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002192static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 .substreams = 1,
2194 .channels_min = 2,
2195 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002196 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002198 .open = alc_playback_pcm_open,
2199 .prepare = alc_playback_pcm_prepare,
2200 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 },
2202};
2203
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002204static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002205 .substreams = 1,
2206 .channels_min = 2,
2207 .channels_max = 2,
2208 /* NID is set in alc_build_pcms */
2209};
2210
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002211static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002212 .substreams = 1,
2213 .channels_min = 2,
2214 .channels_max = 2,
2215 /* NID is set in alc_build_pcms */
2216};
2217
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002218static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002219 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 .channels_min = 2,
2221 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002222 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002224 .prepare = alc_alt_capture_pcm_prepare,
2225 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 },
2227};
2228
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002229static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 .substreams = 1,
2231 .channels_min = 2,
2232 .channels_max = 2,
2233 /* NID is set in alc_build_pcms */
2234 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002235 .open = alc_dig_playback_pcm_open,
2236 .close = alc_dig_playback_pcm_close,
2237 .prepare = alc_dig_playback_pcm_prepare,
2238 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 },
2240};
2241
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002242static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 .substreams = 1,
2244 .channels_min = 2,
2245 .channels_max = 2,
2246 /* NID is set in alc_build_pcms */
2247};
2248
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002249/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002250static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002251 .substreams = 0,
2252 .channels_min = 0,
2253 .channels_max = 0,
2254};
2255
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256static int alc_build_pcms(struct hda_codec *codec)
2257{
2258 struct alc_spec *spec = codec->spec;
2259 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002260 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 int i;
2262
2263 codec->num_pcms = 1;
2264 codec->pcm_info = info;
2265
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002266 if (spec->no_analog)
2267 goto skip_analog;
2268
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002269 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2270 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002272
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002273 if (spec->multiout.dac_nids > 0) {
2274 p = spec->stream_analog_playback;
2275 if (!p)
2276 p = &alc_pcm_analog_playback;
2277 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002278 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2279 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002280 if (spec->adc_nids) {
2281 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002282 if (!p) {
2283 if (spec->dyn_adc_switch)
2284 p = &dyn_adc_pcm_analog_capture;
2285 else
2286 p = &alc_pcm_analog_capture;
2287 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002288 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002289 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
Takashi Iwai4a471b72005-12-07 13:56:29 +01002292 if (spec->channel_mode) {
2293 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2294 for (i = 0; i < spec->num_channel_mode; i++) {
2295 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2296 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2297 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 }
2299 }
2300
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002301 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002302 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002304 snprintf(spec->stream_name_digital,
2305 sizeof(spec->stream_name_digital),
2306 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002307 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002308 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002309 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002311 if (spec->dig_out_type)
2312 info->pcm_type = spec->dig_out_type;
2313 else
2314 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002315 if (spec->multiout.dig_out_nid) {
2316 p = spec->stream_digital_playback;
2317 if (!p)
2318 p = &alc_pcm_digital_playback;
2319 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2321 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002322 if (spec->dig_in_nid) {
2323 p = spec->stream_digital_capture;
2324 if (!p)
2325 p = &alc_pcm_digital_capture;
2326 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2328 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002329 /* FIXME: do we need this for all Realtek codec models? */
2330 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 }
2332
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002333 if (spec->no_analog)
2334 return 0;
2335
Takashi Iwaie08a0072006-09-07 17:52:14 +02002336 /* If the use of more than one ADC is requested for the current
2337 * model, configure a second analog capture-only PCM.
2338 */
2339 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002340 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002341 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002342 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002343 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002344 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002345 p = spec->stream_analog_alt_playback;
2346 if (!p)
2347 p = &alc_pcm_analog_alt_playback;
2348 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002349 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2350 spec->alt_dac_nid;
2351 } else {
2352 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2353 alc_pcm_null_stream;
2354 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2355 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002356 if (spec->num_adc_nids > 1) {
2357 p = spec->stream_analog_alt_capture;
2358 if (!p)
2359 p = &alc_pcm_analog_alt_capture;
2360 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002361 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2362 spec->adc_nids[1];
2363 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2364 spec->num_adc_nids - 1;
2365 } else {
2366 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2367 alc_pcm_null_stream;
2368 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002369 }
2370 }
2371
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 return 0;
2373}
2374
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002375static inline void alc_shutup(struct hda_codec *codec)
2376{
Takashi Iwai1c716152011-04-07 10:37:16 +02002377 struct alc_spec *spec = codec->spec;
2378
2379 if (spec && spec->shutup)
2380 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002381 snd_hda_shutup_pins(codec);
2382}
2383
Takashi Iwai603c4012008-07-30 15:01:44 +02002384static void alc_free_kctls(struct hda_codec *codec)
2385{
2386 struct alc_spec *spec = codec->spec;
2387
2388 if (spec->kctls.list) {
2389 struct snd_kcontrol_new *kctl = spec->kctls.list;
2390 int i;
2391 for (i = 0; i < spec->kctls.used; i++)
2392 kfree(kctl[i].name);
2393 }
2394 snd_array_free(&spec->kctls);
2395}
2396
Takashi Iwai23c09b02011-08-19 09:05:35 +02002397static void alc_free_bind_ctls(struct hda_codec *codec)
2398{
2399 struct alc_spec *spec = codec->spec;
2400 if (spec->bind_ctls.list) {
2401 struct hda_bind_ctls **ctl = spec->bind_ctls.list;
2402 int i;
2403 for (i = 0; i < spec->bind_ctls.used; i++)
2404 kfree(ctl[i]);
2405 }
2406 snd_array_free(&spec->bind_ctls);
2407}
2408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409static void alc_free(struct hda_codec *codec)
2410{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002411 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002412
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002413 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002414 return;
2415
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002416 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002417 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002418 alc_free_kctls(codec);
Takashi Iwai23c09b02011-08-19 09:05:35 +02002419 alc_free_bind_ctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002420 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002421 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422}
2423
Hector Martinf5de24b2009-12-20 22:51:31 +01002424#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002425static void alc_power_eapd(struct hda_codec *codec)
2426{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002427 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002428}
2429
Hector Martinf5de24b2009-12-20 22:51:31 +01002430static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2431{
2432 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002433 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002434 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002435 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002436 return 0;
2437}
2438#endif
2439
Takashi Iwai2a439522011-07-26 09:52:50 +02002440#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002441static int alc_resume(struct hda_codec *codec)
2442{
Takashi Iwai1c716152011-04-07 10:37:16 +02002443 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002444 codec->patch_ops.init(codec);
2445 snd_hda_codec_resume_amp(codec);
2446 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002447 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002448 return 0;
2449}
Takashi Iwaie044c392008-10-27 16:56:24 +01002450#endif
2451
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452/*
2453 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002454static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 .build_controls = alc_build_controls,
2456 .build_pcms = alc_build_pcms,
2457 .init = alc_init,
2458 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002459 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002460#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002461 .resume = alc_resume,
2462#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002463#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002464 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002465 .check_power_status = alc_check_power_status,
2466#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002467 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468};
2469
Kailang Yangc027ddc2010-03-19 11:33:06 +01002470/* replace the codec chip_name with the given string */
2471static int alc_codec_rename(struct hda_codec *codec, const char *name)
2472{
2473 kfree(codec->chip_name);
2474 codec->chip_name = kstrdup(name, GFP_KERNEL);
2475 if (!codec->chip_name) {
2476 alc_free(codec);
2477 return -ENOMEM;
2478 }
2479 return 0;
2480}
2481
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002482/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002483 * Automatic parse of I/O pins from the BIOS configuration
2484 */
2485
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002486enum {
2487 ALC_CTL_WIDGET_VOL,
2488 ALC_CTL_WIDGET_MUTE,
2489 ALC_CTL_BIND_MUTE,
Takashi Iwai23c09b02011-08-19 09:05:35 +02002490 ALC_CTL_BIND_VOL,
2491 ALC_CTL_BIND_SW,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002492};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002493static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002494 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2495 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002496 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwai23c09b02011-08-19 09:05:35 +02002497 HDA_BIND_VOL(NULL, 0),
2498 HDA_BIND_SW(NULL, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002499};
2500
2501/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002502static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002503 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002504{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002505 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002506
Takashi Iwaice764ab2011-04-27 16:35:23 +02002507 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002508 if (!knew)
2509 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002510 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002511 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002512 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002513 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002514 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002515 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002516 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002517 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002518 return 0;
2519}
2520
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002521static int add_control_with_pfx(struct alc_spec *spec, int type,
2522 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002523 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002524{
2525 char name[32];
2526 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002527 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002528}
2529
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002530#define add_pb_vol_ctrl(spec, type, pfx, val) \
2531 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2532#define add_pb_sw_ctrl(spec, type, pfx, val) \
2533 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2534#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2535 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2536#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2537 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002538
Takashi Iwai23c09b02011-08-19 09:05:35 +02002539static const char * const channel_name[4] = {
2540 "Front", "Surround", "CLFE", "Side"
2541};
2542
Takashi Iwai6843ca12011-06-24 11:03:58 +02002543static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2544 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002545{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002546 struct auto_pin_cfg *cfg = &spec->autocfg;
2547
Takashi Iwai6843ca12011-06-24 11:03:58 +02002548 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002549 if (cfg->line_outs == 1 && !spec->multi_ios &&
2550 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002551 return "Master";
2552
2553 switch (cfg->line_out_type) {
2554 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002555 if (cfg->line_outs == 1)
2556 return "Speaker";
2557 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002558 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002559 /* for multi-io case, only the primary out */
2560 if (ch && spec->multi_ios)
2561 break;
2562 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002563 return "Headphone";
2564 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002565 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002566 return "PCM";
2567 break;
2568 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02002569 if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name)))
2570 return "PCM";
2571
2572 return channel_name[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002573}
2574
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002575/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002576static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002577 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002578 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002579{
Kailang Yangdf694da2005-12-05 19:42:22 +01002580 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002581
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002582 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002583 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2584 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002585 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002586 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002587 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2588 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002589 return err;
2590 return 0;
2591}
2592
Takashi Iwai05f5f472009-08-25 13:10:18 +02002593static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002594{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002595 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2596 return (pincap & AC_PINCAP_IN) != 0;
2597}
2598
Takashi Iwai1d045db2011-07-07 18:23:21 +02002599/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002600static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002601{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002602 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002603 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002604 hda_nid_t *adc_nids = spec->private_adc_nids;
2605 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2606 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2607 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002608 int i, nums = 0;
2609
2610 nid = codec->start_nid;
2611 for (i = 0; i < codec->num_nodes; i++, nid++) {
2612 hda_nid_t src;
2613 const hda_nid_t *list;
2614 unsigned int caps = get_wcaps(codec, nid);
2615 int type = get_wcaps_type(caps);
2616
2617 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2618 continue;
2619 adc_nids[nums] = nid;
2620 cap_nids[nums] = nid;
2621 src = nid;
2622 for (;;) {
2623 int n;
2624 type = get_wcaps_type(get_wcaps(codec, src));
2625 if (type == AC_WID_PIN)
2626 break;
2627 if (type == AC_WID_AUD_SEL) {
2628 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002629 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002630 break;
2631 }
2632 n = snd_hda_get_conn_list(codec, src, &list);
2633 if (n > 1) {
2634 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002635 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002636 break;
2637 } else if (n != 1)
2638 break;
2639 src = *list;
2640 }
2641 if (++nums >= max_nums)
2642 break;
2643 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002644 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002645 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002646 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002647 return nums;
2648}
2649
Takashi Iwai05f5f472009-08-25 13:10:18 +02002650/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002651static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002652{
2653 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002654 const struct auto_pin_cfg *cfg = &spec->autocfg;
2655 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002656 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002657 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002658 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002659 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002660
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002661 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002662 if (num_adcs < 0)
2663 return 0;
2664
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002665 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002666 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002667 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002668
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002669 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002670 if (!alc_is_input_pin(codec, pin))
2671 continue;
2672
David Henningsson5322bf22011-01-05 11:03:56 +01002673 label = hda_get_autocfg_input_label(codec, cfg, i);
2674 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002675 type_idx++;
2676 else
2677 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002678 prev_label = label;
2679
Takashi Iwai05f5f472009-08-25 13:10:18 +02002680 if (mixer) {
2681 idx = get_connection_index(codec, mixer, pin);
2682 if (idx >= 0) {
2683 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002684 label, type_idx,
2685 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002686 if (err < 0)
2687 return err;
2688 }
2689 }
2690
Takashi Iwaib7821702011-07-06 15:12:46 +02002691 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002692 hda_nid_t cap = spec->capsrc_nids ?
2693 spec->capsrc_nids[c] : spec->adc_nids[c];
2694 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002695 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002696 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002697 snd_hda_add_imux_item(imux, label, idx, NULL);
2698 break;
2699 }
2700 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002701 }
Takashi Iwai21268962011-07-07 15:01:13 +02002702
2703 spec->num_mux_defs = 1;
2704 spec->input_mux = imux;
2705
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002706 return 0;
2707}
2708
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002709static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2710 unsigned int pin_type)
2711{
2712 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2713 pin_type);
2714 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002715 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2716 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002717 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002718}
2719
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002720static int get_pin_type(int line_out_type)
2721{
2722 if (line_out_type == AUTO_PIN_HP_OUT)
2723 return PIN_HP;
2724 else
2725 return PIN_OUT;
2726}
2727
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002728static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002729{
2730 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002731 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002732 int i;
2733
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002734 for (i = 0; i < cfg->num_inputs; i++) {
2735 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002736 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002737 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002738 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002739 snd_hda_codec_write(codec, nid, 0,
2740 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002741 AMP_OUT_MUTE);
2742 }
2743 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002744
2745 /* mute all loopback inputs */
2746 if (spec->mixer_nid) {
2747 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2748 for (i = 0; i < nums; i++)
2749 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2750 AC_VERB_SET_AMP_GAIN_MUTE,
2751 AMP_IN_MUTE(i));
2752 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002753}
2754
Takashi Iwai7085ec12009-10-02 09:03:58 +02002755/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002756static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002757{
Takashi Iwai604401a2011-04-27 15:14:23 +02002758 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002759 int i, num;
2760
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002761 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2762 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002763 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2764 for (i = 0; i < num; i++) {
2765 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2766 return list[i];
2767 }
2768 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002769}
2770
Takashi Iwai604401a2011-04-27 15:14:23 +02002771/* go down to the selector widget before the mixer */
2772static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2773{
2774 hda_nid_t srcs[5];
2775 int num = snd_hda_get_connections(codec, pin, srcs,
2776 ARRAY_SIZE(srcs));
2777 if (num != 1 ||
2778 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2779 return pin;
2780 return srcs[0];
2781}
2782
Takashi Iwai7085ec12009-10-02 09:03:58 +02002783/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002784static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002785 hda_nid_t dac)
2786{
David Henningssoncc1c4522010-11-24 14:17:47 +01002787 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002788 int i, num;
2789
Takashi Iwai604401a2011-04-27 15:14:23 +02002790 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002791 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2792 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002793 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002794 return mix[i];
2795 }
2796 return 0;
2797}
2798
Takashi Iwaice764ab2011-04-27 16:35:23 +02002799/* select the connection from pin to DAC if needed */
2800static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2801 hda_nid_t dac)
2802{
2803 hda_nid_t mix[5];
2804 int i, num;
2805
2806 pin = alc_go_down_to_selector(codec, pin);
2807 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2808 if (num < 2)
2809 return 0;
2810 for (i = 0; i < num; i++) {
2811 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2812 snd_hda_codec_update_cache(codec, pin, 0,
2813 AC_VERB_SET_CONNECT_SEL, i);
2814 return 0;
2815 }
2816 }
2817 return 0;
2818}
2819
Takashi Iwai7085ec12009-10-02 09:03:58 +02002820/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002821static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002822{
2823 struct alc_spec *spec = codec->spec;
2824 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002825 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002826
Takashi Iwai604401a2011-04-27 15:14:23 +02002827 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002828 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002829 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002830 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002831 if (!nid)
2832 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002833 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2834 spec->multiout.num_dacs))
2835 continue;
Takashi Iwaic2674682011-08-24 17:57:44 +02002836 if (found_in_nid_list(nid, spec->multiout.hp_out_nid,
2837 ARRAY_SIZE(spec->multiout.hp_out_nid)))
2838 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002839 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2840 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2841 continue;
2842 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002843 }
2844 return 0;
2845}
2846
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002847static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2848{
2849 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2850 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2851 return alc_auto_look_for_dac(codec, pin);
2852 return 0;
2853}
2854
Takashi Iwaic2674682011-08-24 17:57:44 +02002855static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
2856 const hda_nid_t *pins, hda_nid_t *dacs)
2857{
2858 int i;
2859
2860 if (num_outs && !dacs[0]) {
2861 dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
2862 if (!dacs[0])
2863 return 0;
2864 }
2865
2866 for (i = 1; i < num_outs; i++)
2867 dacs[i] = get_dac_if_single(codec, pins[i]);
2868 for (i = 1; i < num_outs; i++) {
2869 if (!dacs[i])
2870 dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
2871 }
2872 return 0;
2873}
2874
2875static int alc_auto_fill_multi_ios(struct hda_codec *codec,
2876 unsigned int location);
2877
Takashi Iwai7085ec12009-10-02 09:03:58 +02002878/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002879static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002880{
2881 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002882 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002883 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002884 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002885
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002886 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002887 /* set num_dacs once to full for alc_auto_look_for_dac() */
2888 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwaie23832a2011-08-23 18:16:56 +02002889 spec->multiout.hp_out_nid[0] = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002890 spec->multiout.extra_out_nid[0] = 0;
2891 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2892 spec->multiout.dac_nids = spec->private_dac_nids;
2893
2894 /* fill hard-wired DACs first */
2895 if (!redone) {
2896 for (i = 0; i < cfg->line_outs; i++)
2897 spec->private_dac_nids[i] =
2898 get_dac_if_single(codec, cfg->line_out_pins[i]);
2899 if (cfg->hp_outs)
Takashi Iwaie23832a2011-08-23 18:16:56 +02002900 spec->multiout.hp_out_nid[0] =
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002901 get_dac_if_single(codec, cfg->hp_pins[0]);
2902 if (cfg->speaker_outs)
2903 spec->multiout.extra_out_nid[0] =
2904 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002905 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002906
2907 for (i = 0; i < cfg->line_outs; i++) {
2908 hda_nid_t pin = cfg->line_out_pins[i];
2909 if (spec->private_dac_nids[i])
2910 continue;
2911 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2912 if (!spec->private_dac_nids[i] && !redone) {
2913 /* if we can't find primary DACs, re-probe without
2914 * checking the hard-wired DACs
2915 */
2916 redone = true;
2917 goto again;
2918 }
2919 }
2920
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002921 /* re-count num_dacs and squash invalid entries */
2922 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002923 for (i = 0; i < cfg->line_outs; i++) {
2924 if (spec->private_dac_nids[i])
2925 spec->multiout.num_dacs++;
2926 else
2927 memmove(spec->private_dac_nids + i,
2928 spec->private_dac_nids + i + 1,
2929 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2930 }
2931
Takashi Iwaic2674682011-08-24 17:57:44 +02002932 if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
2933 /* try to fill multi-io first */
2934 unsigned int location, defcfg;
2935 int num_pins;
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002936
Takashi Iwaic2674682011-08-24 17:57:44 +02002937 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
2938 location = get_defcfg_location(defcfg);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002939
Takashi Iwaic2674682011-08-24 17:57:44 +02002940 num_pins = alc_auto_fill_multi_ios(codec, location);
2941 if (num_pins > 0) {
2942 spec->multi_ios = num_pins;
2943 spec->ext_channel_count = 2;
2944 spec->multiout.num_dacs = num_pins + 1;
2945 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02002946 }
Takashi Iwaic2674682011-08-24 17:57:44 +02002947
2948 alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins,
2949 spec->multiout.hp_out_nid);
2950 alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins,
2951 spec->multiout.extra_out_nid);
2952
Takashi Iwai23c09b02011-08-19 09:05:35 +02002953 return 0;
2954}
2955
Takashi Iwai343a04b2011-07-06 14:28:39 +02002956static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002957 const char *pfx, int cidx,
2958 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002959{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002960 if (!nid)
2961 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002962 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2963 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002964}
2965
Takashi Iwai343a04b2011-07-06 14:28:39 +02002966#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2967 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002968
2969/* create a mute-switch for the given mixer widget;
2970 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2971 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002972static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002973 const char *pfx, int cidx,
2974 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002975{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002976 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002977 int type;
2978 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002979 if (!nid)
2980 return 0;
2981 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2982 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2983 type = ALC_CTL_WIDGET_MUTE;
2984 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2985 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002986 type = ALC_CTL_WIDGET_MUTE;
2987 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2988 } else {
2989 type = ALC_CTL_BIND_MUTE;
2990 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2991 }
2992 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002993}
2994
Takashi Iwai343a04b2011-07-06 14:28:39 +02002995#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2996 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002997
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002998static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2999 hda_nid_t pin, hda_nid_t dac)
3000{
3001 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
3002 if (nid_has_mute(codec, pin, HDA_OUTPUT))
3003 return pin;
3004 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
3005 return mix;
3006 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
3007 return dac;
3008 return 0;
3009}
3010
3011static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
3012 hda_nid_t pin, hda_nid_t dac)
3013{
3014 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
3015 if (nid_has_volume(codec, dac, HDA_OUTPUT))
3016 return dac;
3017 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
3018 return mix;
3019 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
3020 return pin;
3021 return 0;
3022}
3023
Takashi Iwai7085ec12009-10-02 09:03:58 +02003024/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02003025static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003026 const struct auto_pin_cfg *cfg)
3027{
3028 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003029 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003030
Takashi Iwaice764ab2011-04-27 16:35:23 +02003031 noutputs = cfg->line_outs;
3032 if (spec->multi_ios > 0)
3033 noutputs += spec->multi_ios;
3034
3035 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02003036 const char *name;
3037 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003038 hda_nid_t dac, pin;
3039 hda_nid_t sw, vol;
3040
3041 dac = spec->multiout.dac_nids[i];
3042 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003043 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003044 if (i >= cfg->line_outs)
3045 pin = spec->multi_io[i - 1].pin;
3046 else
3047 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003048
3049 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3050 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02003051 name = alc_get_line_out_pfx(spec, i, true, &index);
Takashi Iwai9c4e84d2011-08-24 17:27:52 +02003052 if (!name || !strcmp(name, "CLFE")) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003053 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003054 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003055 if (err < 0)
3056 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003057 err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003058 if (err < 0)
3059 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003060 err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003061 if (err < 0)
3062 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003063 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003064 if (err < 0)
3065 return err;
3066 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003067 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003068 if (err < 0)
3069 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003070 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003071 if (err < 0)
3072 return err;
3073 }
3074 }
3075 return 0;
3076}
3077
Takashi Iwai343a04b2011-07-06 14:28:39 +02003078static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai23c09b02011-08-19 09:05:35 +02003079 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003080{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003081 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003082 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003083 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003084
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003085 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02003086 /* the corresponding DAC is already occupied */
3087 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
3088 return 0; /* no way */
3089 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02003090 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003091 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3092 }
3093
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003094 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3095 vol = alc_look_for_out_vol_nid(codec, pin, dac);
3096 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003097 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003098 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003099 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003100 if (err < 0)
3101 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003102 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003103}
3104
Takashi Iwai23c09b02011-08-19 09:05:35 +02003105static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
3106 unsigned int nums,
3107 struct hda_ctl_ops *ops)
3108{
3109 struct alc_spec *spec = codec->spec;
3110 struct hda_bind_ctls **ctlp, *ctl;
3111 snd_array_init(&spec->bind_ctls, sizeof(ctl), 8);
3112 ctlp = snd_array_new(&spec->bind_ctls);
3113 if (!ctlp)
3114 return NULL;
3115 ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL);
3116 *ctlp = ctl;
3117 if (ctl)
3118 ctl->ops = ops;
3119 return ctl;
3120}
3121
3122/* add playback controls for speaker and HP outputs */
3123static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
3124 const hda_nid_t *pins,
3125 const hda_nid_t *dacs,
3126 const char *pfx)
3127{
3128 struct alc_spec *spec = codec->spec;
3129 struct hda_bind_ctls *ctl;
3130 char name[32];
3131 int i, n, err;
3132
3133 if (!num_pins || !pins[0])
3134 return 0;
3135
3136 if (num_pins == 1)
3137 return alc_auto_create_extra_out(codec, *pins, *dacs, pfx);
3138
3139 if (dacs[num_pins - 1]) {
3140 /* OK, we have a multi-output system with individual volumes */
3141 for (i = 0; i < num_pins; i++) {
3142 snprintf(name, sizeof(name), "%s %s",
3143 pfx, channel_name[i]);
3144 err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
3145 name);
3146 if (err < 0)
3147 return err;
3148 }
3149 return 0;
3150 }
3151
3152 /* Let's create a bind-controls */
3153 ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw);
3154 if (!ctl)
3155 return -ENOMEM;
3156 n = 0;
3157 for (i = 0; i < num_pins; i++) {
3158 if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP)
3159 ctl->values[n++] =
3160 HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT);
3161 }
3162 if (n) {
3163 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
3164 err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl);
3165 if (err < 0)
3166 return err;
3167 }
3168
3169 ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
3170 if (!ctl)
3171 return -ENOMEM;
3172 n = 0;
3173 for (i = 0; i < num_pins; i++) {
3174 hda_nid_t vol;
3175 if (!pins[i] || !dacs[i])
3176 continue;
3177 vol = alc_look_for_out_vol_nid(codec, pins[i], dacs[i]);
3178 if (vol)
3179 ctl->values[n++] =
3180 HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT);
3181 }
3182 if (n) {
3183 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
3184 err = add_control(spec, ALC_CTL_BIND_VOL, name, 0, (long)ctl);
3185 if (err < 0)
3186 return err;
3187 }
3188 return 0;
3189}
3190
Takashi Iwai343a04b2011-07-06 14:28:39 +02003191static int alc_auto_create_hp_out(struct hda_codec *codec)
3192{
3193 struct alc_spec *spec = codec->spec;
Takashi Iwaie23832a2011-08-23 18:16:56 +02003194 return alc_auto_create_extra_outs(codec, spec->autocfg.hp_outs,
3195 spec->autocfg.hp_pins,
3196 spec->multiout.hp_out_nid,
3197 "Headphone");
Takashi Iwai343a04b2011-07-06 14:28:39 +02003198}
3199
3200static int alc_auto_create_speaker_out(struct hda_codec *codec)
3201{
3202 struct alc_spec *spec = codec->spec;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003203 return alc_auto_create_extra_outs(codec, spec->autocfg.speaker_outs,
3204 spec->autocfg.speaker_pins,
3205 spec->multiout.extra_out_nid,
3206 "Speaker");
Takashi Iwai343a04b2011-07-06 14:28:39 +02003207}
3208
Takashi Iwai343a04b2011-07-06 14:28:39 +02003209static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003210 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003211 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003212{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003213 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003214 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003215 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003216
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003217 alc_set_pin_output(codec, pin, pin_type);
3218 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003219 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003220 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003221 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003222 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003223 mix = srcs[i];
3224 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003225 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003226 if (!mix)
3227 return;
3228
3229 /* need the manual connection? */
3230 if (num > 1)
3231 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3232 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003233 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3234 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003235 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003236 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003237 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003238 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003239 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003240 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3241 if (nid)
3242 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3243 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003244}
3245
Takashi Iwai343a04b2011-07-06 14:28:39 +02003246static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003247{
3248 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003249 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003250 int i;
3251
3252 for (i = 0; i <= HDA_SIDE; i++) {
3253 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3254 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003255 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003256 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003257 }
3258}
3259
Takashi Iwai343a04b2011-07-06 14:28:39 +02003260static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003261{
3262 struct alc_spec *spec = codec->spec;
Takashi Iwai8cd07752011-08-23 15:16:22 +02003263 int i;
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003264 hda_nid_t pin, dac;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003265
David Henningsson636030e2011-10-12 19:26:03 +02003266 for (i = 0; i < spec->autocfg.hp_outs; i++) {
Takashi Iwaie23832a2011-08-23 18:16:56 +02003267 pin = spec->autocfg.hp_pins[i];
3268 if (!pin)
3269 break;
3270 dac = spec->multiout.hp_out_nid[i];
3271 if (!dac) {
3272 if (i > 0 && spec->multiout.hp_out_nid[0])
3273 dac = spec->multiout.hp_out_nid[0];
3274 else
3275 dac = spec->multiout.dac_nids[0];
3276 }
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003277 alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
3278 }
Takashi Iwai8cd07752011-08-23 15:16:22 +02003279 for (i = 0; i < spec->autocfg.speaker_outs; i++) {
3280 pin = spec->autocfg.speaker_pins[i];
3281 if (!pin)
3282 break;
3283 dac = spec->multiout.extra_out_nid[i];
3284 if (!dac) {
3285 if (i > 0 && spec->multiout.extra_out_nid[0])
3286 dac = spec->multiout.extra_out_nid[0];
3287 else
3288 dac = spec->multiout.dac_nids[0];
3289 }
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003290 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
3291 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003292}
3293
Takashi Iwaice764ab2011-04-27 16:35:23 +02003294/*
3295 * multi-io helper
3296 */
3297static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3298 unsigned int location)
3299{
3300 struct alc_spec *spec = codec->spec;
3301 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaic2674682011-08-24 17:57:44 +02003302 hda_nid_t prime_dac = spec->private_dac_nids[0];
Takashi Iwaice764ab2011-04-27 16:35:23 +02003303 int type, i, num_pins = 0;
3304
3305 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3306 for (i = 0; i < cfg->num_inputs; i++) {
3307 hda_nid_t nid = cfg->inputs[i].pin;
3308 hda_nid_t dac;
3309 unsigned int defcfg, caps;
3310 if (cfg->inputs[i].type != type)
3311 continue;
3312 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3313 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3314 continue;
3315 if (location && get_defcfg_location(defcfg) != location)
3316 continue;
3317 caps = snd_hda_query_pin_caps(codec, nid);
3318 if (!(caps & AC_PINCAP_OUT))
3319 continue;
3320 dac = alc_auto_look_for_dac(codec, nid);
3321 if (!dac)
3322 continue;
3323 spec->multi_io[num_pins].pin = nid;
3324 spec->multi_io[num_pins].dac = dac;
3325 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003326 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003327 }
3328 }
3329 spec->multiout.num_dacs = 1;
Takashi Iwaic2674682011-08-24 17:57:44 +02003330 if (num_pins < 2) {
3331 /* clear up again */
3332 memset(spec->private_dac_nids, 0,
3333 sizeof(spec->private_dac_nids));
3334 spec->private_dac_nids[0] = prime_dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003335 return 0;
Takashi Iwaic2674682011-08-24 17:57:44 +02003336 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003337 return num_pins;
3338}
3339
3340static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3341 struct snd_ctl_elem_info *uinfo)
3342{
3343 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3344 struct alc_spec *spec = codec->spec;
3345
3346 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3347 uinfo->count = 1;
3348 uinfo->value.enumerated.items = spec->multi_ios + 1;
3349 if (uinfo->value.enumerated.item > spec->multi_ios)
3350 uinfo->value.enumerated.item = spec->multi_ios;
3351 sprintf(uinfo->value.enumerated.name, "%dch",
3352 (uinfo->value.enumerated.item + 1) * 2);
3353 return 0;
3354}
3355
3356static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3357 struct snd_ctl_elem_value *ucontrol)
3358{
3359 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3360 struct alc_spec *spec = codec->spec;
3361 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3362 return 0;
3363}
3364
3365static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3366{
3367 struct alc_spec *spec = codec->spec;
3368 hda_nid_t nid = spec->multi_io[idx].pin;
3369
3370 if (!spec->multi_io[idx].ctl_in)
3371 spec->multi_io[idx].ctl_in =
3372 snd_hda_codec_read(codec, nid, 0,
3373 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3374 if (output) {
3375 snd_hda_codec_update_cache(codec, nid, 0,
3376 AC_VERB_SET_PIN_WIDGET_CONTROL,
3377 PIN_OUT);
3378 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3379 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3380 HDA_AMP_MUTE, 0);
3381 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3382 } else {
3383 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3384 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3385 HDA_AMP_MUTE, HDA_AMP_MUTE);
3386 snd_hda_codec_update_cache(codec, nid, 0,
3387 AC_VERB_SET_PIN_WIDGET_CONTROL,
3388 spec->multi_io[idx].ctl_in);
3389 }
3390 return 0;
3391}
3392
3393static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3394 struct snd_ctl_elem_value *ucontrol)
3395{
3396 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3397 struct alc_spec *spec = codec->spec;
3398 int i, ch;
3399
3400 ch = ucontrol->value.enumerated.item[0];
3401 if (ch < 0 || ch > spec->multi_ios)
3402 return -EINVAL;
3403 if (ch == (spec->ext_channel_count - 1) / 2)
3404 return 0;
3405 spec->ext_channel_count = (ch + 1) * 2;
3406 for (i = 0; i < spec->multi_ios; i++)
3407 alc_set_multi_io(codec, i, i < ch);
3408 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003409 if (spec->need_dac_fix && !spec->const_channel_count)
3410 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003411 return 1;
3412}
3413
Takashi Iwaia9111322011-05-02 11:30:18 +02003414static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003415 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3416 .name = "Channel Mode",
3417 .info = alc_auto_ch_mode_info,
3418 .get = alc_auto_ch_mode_get,
3419 .put = alc_auto_ch_mode_put,
3420};
3421
Takashi Iwai23c09b02011-08-19 09:05:35 +02003422static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003423{
3424 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003425
Takashi Iwaic2674682011-08-24 17:57:44 +02003426 if (spec->multi_ios > 0) {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003427 struct snd_kcontrol_new *knew;
3428
3429 knew = alc_kcontrol_new(spec);
3430 if (!knew)
3431 return -ENOMEM;
3432 *knew = alc_auto_channel_mode_enum;
3433 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3434 if (!knew->name)
3435 return -ENOMEM;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003436 }
3437 return 0;
3438}
3439
Takashi Iwai1d045db2011-07-07 18:23:21 +02003440/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3441 * active input pins
3442 */
3443static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3444{
3445 struct alc_spec *spec = codec->spec;
3446 const struct hda_input_mux *imux;
3447 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3448 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3449 int i, n, nums;
3450
3451 imux = spec->input_mux;
3452 if (!imux)
3453 return;
3454 if (spec->dyn_adc_switch)
3455 return;
3456
3457 nums = 0;
3458 for (n = 0; n < spec->num_adc_nids; n++) {
3459 hda_nid_t cap = spec->private_capsrc_nids[n];
3460 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3461 for (i = 0; i < imux->num_items; i++) {
3462 hda_nid_t pin = spec->imux_pins[i];
3463 if (pin) {
3464 if (get_connection_index(codec, cap, pin) < 0)
3465 break;
3466 } else if (num_conns <= imux->items[i].index)
3467 break;
3468 }
3469 if (i >= imux->num_items) {
3470 adc_nids[nums] = spec->private_adc_nids[n];
3471 capsrc_nids[nums++] = cap;
3472 }
3473 }
3474 if (!nums) {
3475 /* check whether ADC-switch is possible */
3476 if (!alc_check_dyn_adc_switch(codec)) {
3477 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3478 " using fallback 0x%x\n",
3479 codec->chip_name, spec->private_adc_nids[0]);
3480 spec->num_adc_nids = 1;
3481 spec->auto_mic = 0;
3482 return;
3483 }
3484 } else if (nums != spec->num_adc_nids) {
3485 memcpy(spec->private_adc_nids, adc_nids,
3486 nums * sizeof(hda_nid_t));
3487 memcpy(spec->private_capsrc_nids, capsrc_nids,
3488 nums * sizeof(hda_nid_t));
3489 spec->num_adc_nids = nums;
3490 }
3491
3492 if (spec->auto_mic)
3493 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3494 else if (spec->input_mux->num_items == 1)
3495 spec->num_adc_nids = 1; /* reduce to a single ADC */
3496}
3497
3498/*
3499 * initialize ADC paths
3500 */
3501static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3502{
3503 struct alc_spec *spec = codec->spec;
3504 hda_nid_t nid;
3505
3506 nid = spec->adc_nids[adc_idx];
3507 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003508 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003509 snd_hda_codec_write(codec, nid, 0,
3510 AC_VERB_SET_AMP_GAIN_MUTE,
3511 AMP_IN_MUTE(0));
3512 return;
3513 }
3514 if (!spec->capsrc_nids)
3515 return;
3516 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003517 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003518 snd_hda_codec_write(codec, nid, 0,
3519 AC_VERB_SET_AMP_GAIN_MUTE,
3520 AMP_OUT_MUTE);
3521}
3522
3523static void alc_auto_init_input_src(struct hda_codec *codec)
3524{
3525 struct alc_spec *spec = codec->spec;
3526 int c, nums;
3527
3528 for (c = 0; c < spec->num_adc_nids; c++)
3529 alc_auto_init_adc(codec, c);
3530 if (spec->dyn_adc_switch)
3531 nums = 1;
3532 else
3533 nums = spec->num_adc_nids;
3534 for (c = 0; c < nums; c++)
3535 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3536}
3537
3538/* add mic boosts if needed */
3539static int alc_auto_add_mic_boost(struct hda_codec *codec)
3540{
3541 struct alc_spec *spec = codec->spec;
3542 struct auto_pin_cfg *cfg = &spec->autocfg;
3543 int i, err;
3544 int type_idx = 0;
3545 hda_nid_t nid;
3546 const char *prev_label = NULL;
3547
3548 for (i = 0; i < cfg->num_inputs; i++) {
3549 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3550 break;
3551 nid = cfg->inputs[i].pin;
3552 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3553 const char *label;
3554 char boost_label[32];
3555
3556 label = hda_get_autocfg_input_label(codec, cfg, i);
3557 if (prev_label && !strcmp(label, prev_label))
3558 type_idx++;
3559 else
3560 type_idx = 0;
3561 prev_label = label;
3562
3563 snprintf(boost_label, sizeof(boost_label),
3564 "%s Boost Volume", label);
3565 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3566 boost_label, type_idx,
3567 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3568 if (err < 0)
3569 return err;
3570 }
3571 }
3572 return 0;
3573}
3574
3575/* select or unmute the given capsrc route */
3576static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3577 int idx)
3578{
3579 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3580 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3581 HDA_AMP_MUTE, 0);
3582 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3583 snd_hda_codec_write_cache(codec, cap, 0,
3584 AC_VERB_SET_CONNECT_SEL, idx);
3585 }
3586}
3587
3588/* set the default connection to that pin */
3589static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3590{
3591 struct alc_spec *spec = codec->spec;
3592 int i;
3593
3594 if (!pin)
3595 return 0;
3596 for (i = 0; i < spec->num_adc_nids; i++) {
3597 hda_nid_t cap = spec->capsrc_nids ?
3598 spec->capsrc_nids[i] : spec->adc_nids[i];
3599 int idx;
3600
3601 idx = get_connection_index(codec, cap, pin);
3602 if (idx < 0)
3603 continue;
3604 select_or_unmute_capsrc(codec, cap, idx);
3605 return i; /* return the found index */
3606 }
3607 return -1; /* not found */
3608}
3609
3610/* initialize some special cases for input sources */
3611static void alc_init_special_input_src(struct hda_codec *codec)
3612{
3613 struct alc_spec *spec = codec->spec;
3614 int i;
3615
3616 for (i = 0; i < spec->autocfg.num_inputs; i++)
3617 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3618}
3619
3620/* assign appropriate capture mixers */
3621static void set_capture_mixer(struct hda_codec *codec)
3622{
3623 struct alc_spec *spec = codec->spec;
3624 static const struct snd_kcontrol_new *caps[2][3] = {
3625 { alc_capture_mixer_nosrc1,
3626 alc_capture_mixer_nosrc2,
3627 alc_capture_mixer_nosrc3 },
3628 { alc_capture_mixer1,
3629 alc_capture_mixer2,
3630 alc_capture_mixer3 },
3631 };
3632
3633 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003634 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003635 if (!spec->capsrc_nids)
3636 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003637 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003638 return; /* no volume in capsrc, too */
3639 spec->vol_in_capsrc = 1;
3640 }
3641
3642 if (spec->num_adc_nids > 0) {
3643 int mux = 0;
3644 int num_adcs = 0;
3645
3646 if (spec->input_mux && spec->input_mux->num_items > 1)
3647 mux = 1;
3648 if (spec->auto_mic) {
3649 num_adcs = 1;
3650 mux = 0;
3651 } else if (spec->dyn_adc_switch)
3652 num_adcs = 1;
3653 if (!num_adcs) {
3654 if (spec->num_adc_nids > 3)
3655 spec->num_adc_nids = 3;
3656 else if (!spec->num_adc_nids)
3657 return;
3658 num_adcs = spec->num_adc_nids;
3659 }
3660 spec->cap_mixer = caps[mux][num_adcs - 1];
3661 }
3662}
3663
3664/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003665 * standard auto-parser initializations
3666 */
3667static void alc_auto_init_std(struct hda_codec *codec)
3668{
3669 struct alc_spec *spec = codec->spec;
3670 alc_auto_init_multi_out(codec);
3671 alc_auto_init_extra_out(codec);
3672 alc_auto_init_analog_input(codec);
3673 alc_auto_init_input_src(codec);
3674 alc_auto_init_digital(codec);
3675 if (spec->unsol_event)
3676 alc_inithook(codec);
3677}
3678
3679/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003680 * Digital-beep handlers
3681 */
3682#ifdef CONFIG_SND_HDA_INPUT_BEEP
3683#define set_beep_amp(spec, nid, idx, dir) \
3684 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3685
3686static const struct snd_pci_quirk beep_white_list[] = {
3687 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3688 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3689 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3690 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3691 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3692 {}
3693};
3694
3695static inline int has_cdefine_beep(struct hda_codec *codec)
3696{
3697 struct alc_spec *spec = codec->spec;
3698 const struct snd_pci_quirk *q;
3699 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3700 if (q)
3701 return q->value;
3702 return spec->cdefine.enable_pcbeep;
3703}
3704#else
3705#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3706#define has_cdefine_beep(codec) 0
3707#endif
3708
3709/* parse the BIOS configuration and set up the alc_spec */
3710/* return 1 if successful, 0 if the proper config is not found,
3711 * or a negative error code
3712 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003713static int alc_parse_auto_config(struct hda_codec *codec,
3714 const hda_nid_t *ignore_nids,
3715 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003716{
3717 struct alc_spec *spec = codec->spec;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003718 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003719 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003720
Takashi Iwai53c334a2011-08-23 18:27:14 +02003721 err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
3722 spec->parse_flags);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003723 if (err < 0)
3724 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003725 if (!cfg->line_outs) {
3726 if (cfg->dig_outs || cfg->dig_in_pin) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003727 spec->multiout.max_channels = 2;
3728 spec->no_analog = 1;
3729 goto dig_only;
3730 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003731 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003732 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02003733
Takashi Iwai06503672011-10-06 08:27:19 +02003734 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
3735 cfg->line_outs <= cfg->hp_outs) {
Takashi Iwai23c09b02011-08-19 09:05:35 +02003736 /* use HP as primary out */
3737 cfg->speaker_outs = cfg->line_outs;
3738 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3739 sizeof(cfg->speaker_pins));
3740 cfg->line_outs = cfg->hp_outs;
3741 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3742 cfg->hp_outs = 0;
3743 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3744 cfg->line_out_type = AUTO_PIN_HP_OUT;
3745 }
3746
Takashi Iwai1d045db2011-07-07 18:23:21 +02003747 err = alc_auto_fill_dac_nids(codec);
3748 if (err < 0)
3749 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003750 err = alc_auto_add_multi_channel_mode(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003751 if (err < 0)
3752 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003753 err = alc_auto_create_multi_out_ctls(codec, cfg);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003754 if (err < 0)
3755 return err;
3756 err = alc_auto_create_hp_out(codec);
3757 if (err < 0)
3758 return err;
3759 err = alc_auto_create_speaker_out(codec);
3760 if (err < 0)
3761 return err;
3762 err = alc_auto_create_input_ctls(codec);
3763 if (err < 0)
3764 return err;
3765
3766 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3767
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003768 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02003769 alc_auto_parse_digital(codec);
3770
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003771 if (!spec->no_analog)
3772 alc_remove_invalid_adc_nids(codec);
3773
3774 if (ssid_nids)
3775 alc_ssid_check(codec, ssid_nids);
3776
3777 if (!spec->no_analog) {
3778 alc_auto_check_switches(codec);
3779 err = alc_auto_add_mic_boost(codec);
3780 if (err < 0)
3781 return err;
3782 }
3783
Takashi Iwai1d045db2011-07-07 18:23:21 +02003784 if (spec->kctls.list)
3785 add_mixer(spec, spec->kctls.list);
3786
Takashi Iwai1d045db2011-07-07 18:23:21 +02003787 return 1;
3788}
3789
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003790static int alc880_parse_auto_config(struct hda_codec *codec)
3791{
3792 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3793 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3794 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
3795}
3796
Takashi Iwai1d045db2011-07-07 18:23:21 +02003797#ifdef CONFIG_SND_HDA_POWER_SAVE
3798static const struct hda_amp_list alc880_loopbacks[] = {
3799 { 0x0b, HDA_INPUT, 0 },
3800 { 0x0b, HDA_INPUT, 1 },
3801 { 0x0b, HDA_INPUT, 2 },
3802 { 0x0b, HDA_INPUT, 3 },
3803 { 0x0b, HDA_INPUT, 4 },
3804 { } /* end */
3805};
3806#endif
3807
3808/*
3809 * board setups
3810 */
3811#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3812#define alc_board_config \
3813 snd_hda_check_board_config
3814#define alc_board_codec_sid_config \
3815 snd_hda_check_board_codec_sid_config
3816#include "alc_quirks.c"
3817#else
3818#define alc_board_config(codec, nums, models, tbl) -1
3819#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3820#define setup_preset(codec, x) /* NOP */
3821#endif
3822
3823/*
3824 * OK, here we have finally the patch for ALC880
3825 */
3826#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3827#include "alc880_quirks.c"
3828#endif
3829
3830static int patch_alc880(struct hda_codec *codec)
3831{
3832 struct alc_spec *spec;
3833 int board_config;
3834 int err;
3835
3836 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3837 if (spec == NULL)
3838 return -ENOMEM;
3839
3840 codec->spec = spec;
3841
3842 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003843 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003844
3845 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3846 alc880_models, alc880_cfg_tbl);
3847 if (board_config < 0) {
3848 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3849 codec->chip_name);
3850 board_config = ALC_MODEL_AUTO;
3851 }
3852
3853 if (board_config == ALC_MODEL_AUTO) {
3854 /* automatic parse from the BIOS config */
3855 err = alc880_parse_auto_config(codec);
3856 if (err < 0) {
3857 alc_free(codec);
3858 return err;
3859 }
3860#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3861 else if (!err) {
3862 printk(KERN_INFO
3863 "hda_codec: Cannot set up configuration "
3864 "from BIOS. Using 3-stack mode...\n");
3865 board_config = ALC880_3ST;
3866 }
3867#endif
3868 }
3869
Takashi Iwai1d045db2011-07-07 18:23:21 +02003870 if (board_config != ALC_MODEL_AUTO)
3871 setup_preset(codec, &alc880_presets[board_config]);
3872
Takashi Iwai60a6a842011-07-27 14:01:24 +02003873 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003874 alc_auto_fill_adc_caps(codec);
3875 alc_rebuild_imux_for_auto_mic(codec);
3876 alc_remove_invalid_adc_nids(codec);
3877 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003878
3879 if (!spec->no_analog && !spec->cap_mixer)
3880 set_capture_mixer(codec);
3881
3882 if (!spec->no_analog) {
3883 err = snd_hda_attach_beep_device(codec, 0x1);
3884 if (err < 0) {
3885 alc_free(codec);
3886 return err;
3887 }
3888 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3889 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003890
3891 spec->vmaster_nid = 0x0c;
3892
3893 codec->patch_ops = alc_patch_ops;
3894 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003895 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003896#ifdef CONFIG_SND_HDA_POWER_SAVE
3897 if (!spec->loopback.amplist)
3898 spec->loopback.amplist = alc880_loopbacks;
3899#endif
3900
3901 return 0;
3902}
3903
3904
3905/*
3906 * ALC260 support
3907 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003908static int alc260_parse_auto_config(struct hda_codec *codec)
3909{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003910 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003911 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
3912 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003913}
3914
Takashi Iwai1d045db2011-07-07 18:23:21 +02003915#ifdef CONFIG_SND_HDA_POWER_SAVE
3916static const struct hda_amp_list alc260_loopbacks[] = {
3917 { 0x07, HDA_INPUT, 0 },
3918 { 0x07, HDA_INPUT, 1 },
3919 { 0x07, HDA_INPUT, 2 },
3920 { 0x07, HDA_INPUT, 3 },
3921 { 0x07, HDA_INPUT, 4 },
3922 { } /* end */
3923};
3924#endif
3925
3926/*
3927 * Pin config fixes
3928 */
3929enum {
3930 PINFIX_HP_DC5750,
3931};
3932
3933static const struct alc_fixup alc260_fixups[] = {
3934 [PINFIX_HP_DC5750] = {
3935 .type = ALC_FIXUP_PINS,
3936 .v.pins = (const struct alc_pincfg[]) {
3937 { 0x11, 0x90130110 }, /* speaker */
3938 { }
3939 }
3940 },
3941};
3942
3943static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3944 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3945 {}
3946};
3947
3948/*
3949 */
3950#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3951#include "alc260_quirks.c"
3952#endif
3953
3954static int patch_alc260(struct hda_codec *codec)
3955{
3956 struct alc_spec *spec;
3957 int err, board_config;
3958
3959 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3960 if (spec == NULL)
3961 return -ENOMEM;
3962
3963 codec->spec = spec;
3964
3965 spec->mixer_nid = 0x07;
3966
3967 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3968 alc260_models, alc260_cfg_tbl);
3969 if (board_config < 0) {
3970 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3971 codec->chip_name);
3972 board_config = ALC_MODEL_AUTO;
3973 }
3974
3975 if (board_config == ALC_MODEL_AUTO) {
3976 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3977 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3978 }
3979
3980 if (board_config == ALC_MODEL_AUTO) {
3981 /* automatic parse from the BIOS config */
3982 err = alc260_parse_auto_config(codec);
3983 if (err < 0) {
3984 alc_free(codec);
3985 return err;
3986 }
3987#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3988 else if (!err) {
3989 printk(KERN_INFO
3990 "hda_codec: Cannot set up configuration "
3991 "from BIOS. Using base mode...\n");
3992 board_config = ALC260_BASIC;
3993 }
3994#endif
3995 }
3996
Takashi Iwai1d045db2011-07-07 18:23:21 +02003997 if (board_config != ALC_MODEL_AUTO)
3998 setup_preset(codec, &alc260_presets[board_config]);
3999
Takashi Iwai60a6a842011-07-27 14:01:24 +02004000 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004001 alc_auto_fill_adc_caps(codec);
4002 alc_rebuild_imux_for_auto_mic(codec);
4003 alc_remove_invalid_adc_nids(codec);
4004 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004005
4006 if (!spec->no_analog && !spec->cap_mixer)
4007 set_capture_mixer(codec);
4008
4009 if (!spec->no_analog) {
4010 err = snd_hda_attach_beep_device(codec, 0x1);
4011 if (err < 0) {
4012 alc_free(codec);
4013 return err;
4014 }
4015 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
4016 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004017
4018 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4019
4020 spec->vmaster_nid = 0x08;
4021
4022 codec->patch_ops = alc_patch_ops;
4023 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02004024 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004025 spec->shutup = alc_eapd_shutup;
4026#ifdef CONFIG_SND_HDA_POWER_SAVE
4027 if (!spec->loopback.amplist)
4028 spec->loopback.amplist = alc260_loopbacks;
4029#endif
4030
4031 return 0;
4032}
4033
4034
4035/*
4036 * ALC882/883/885/888/889 support
4037 *
4038 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
4039 * configuration. Each pin widget can choose any input DACs and a mixer.
4040 * Each ADC is connected from a mixer of all inputs. This makes possible
4041 * 6-channel independent captures.
4042 *
4043 * In addition, an independent DAC for the multi-playback (not used in this
4044 * driver yet).
4045 */
4046#ifdef CONFIG_SND_HDA_POWER_SAVE
4047#define alc882_loopbacks alc880_loopbacks
4048#endif
4049
4050/*
4051 * Pin config fixes
4052 */
4053enum {
4054 PINFIX_ABIT_AW9D_MAX,
4055 PINFIX_LENOVO_Y530,
4056 PINFIX_PB_M5210,
4057 PINFIX_ACER_ASPIRE_7736,
4058};
4059
4060static const struct alc_fixup alc882_fixups[] = {
4061 [PINFIX_ABIT_AW9D_MAX] = {
4062 .type = ALC_FIXUP_PINS,
4063 .v.pins = (const struct alc_pincfg[]) {
4064 { 0x15, 0x01080104 }, /* side */
4065 { 0x16, 0x01011012 }, /* rear */
4066 { 0x17, 0x01016011 }, /* clfe */
4067 { }
4068 }
4069 },
4070 [PINFIX_LENOVO_Y530] = {
4071 .type = ALC_FIXUP_PINS,
4072 .v.pins = (const struct alc_pincfg[]) {
4073 { 0x15, 0x99130112 }, /* rear int speakers */
4074 { 0x16, 0x99130111 }, /* subwoofer */
4075 { }
4076 }
4077 },
4078 [PINFIX_PB_M5210] = {
4079 .type = ALC_FIXUP_VERBS,
4080 .v.verbs = (const struct hda_verb[]) {
4081 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
4082 {}
4083 }
4084 },
4085 [PINFIX_ACER_ASPIRE_7736] = {
4086 .type = ALC_FIXUP_SKU,
4087 .v.sku = ALC_FIXUP_SKU_IGNORE,
4088 },
4089};
4090
4091static const struct snd_pci_quirk alc882_fixup_tbl[] = {
4092 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
4093 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
4094 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
4095 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
4096 {}
4097};
4098
4099/*
4100 * BIOS auto configuration
4101 */
4102/* almost identical with ALC880 parser... */
4103static int alc882_parse_auto_config(struct hda_codec *codec)
4104{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004105 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004106 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4107 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004108}
4109
Takashi Iwai1d045db2011-07-07 18:23:21 +02004110/*
4111 */
4112#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4113#include "alc882_quirks.c"
4114#endif
4115
4116static int patch_alc882(struct hda_codec *codec)
4117{
4118 struct alc_spec *spec;
4119 int err, board_config;
4120
4121 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4122 if (spec == NULL)
4123 return -ENOMEM;
4124
4125 codec->spec = spec;
4126
4127 spec->mixer_nid = 0x0b;
4128
4129 switch (codec->vendor_id) {
4130 case 0x10ec0882:
4131 case 0x10ec0885:
4132 break;
4133 default:
4134 /* ALC883 and variants */
4135 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4136 break;
4137 }
4138
4139 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
4140 alc882_models, alc882_cfg_tbl);
4141
4142 if (board_config < 0)
4143 board_config = alc_board_codec_sid_config(codec,
4144 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
4145
4146 if (board_config < 0) {
4147 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4148 codec->chip_name);
4149 board_config = ALC_MODEL_AUTO;
4150 }
4151
4152 if (board_config == ALC_MODEL_AUTO) {
4153 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
4154 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4155 }
4156
4157 alc_auto_parse_customize_define(codec);
4158
4159 if (board_config == ALC_MODEL_AUTO) {
4160 /* automatic parse from the BIOS config */
4161 err = alc882_parse_auto_config(codec);
4162 if (err < 0) {
4163 alc_free(codec);
4164 return err;
4165 }
4166#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4167 else if (!err) {
4168 printk(KERN_INFO
4169 "hda_codec: Cannot set up configuration "
4170 "from BIOS. Using base mode...\n");
4171 board_config = ALC882_3ST_DIG;
4172 }
4173#endif
4174 }
4175
Takashi Iwai1d045db2011-07-07 18:23:21 +02004176 if (board_config != ALC_MODEL_AUTO)
4177 setup_preset(codec, &alc882_presets[board_config]);
4178
Takashi Iwai60a6a842011-07-27 14:01:24 +02004179 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004180 alc_auto_fill_adc_caps(codec);
4181 alc_rebuild_imux_for_auto_mic(codec);
4182 alc_remove_invalid_adc_nids(codec);
4183 }
4184
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004185 if (!spec->no_analog && !spec->cap_mixer)
4186 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004187
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004188 if (!spec->no_analog && has_cdefine_beep(codec)) {
4189 err = snd_hda_attach_beep_device(codec, 0x1);
4190 if (err < 0) {
4191 alc_free(codec);
4192 return err;
4193 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004194 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004195 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004196
4197 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4198
4199 spec->vmaster_nid = 0x0c;
4200
4201 codec->patch_ops = alc_patch_ops;
4202 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004203 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004204
4205 alc_init_jacks(codec);
4206#ifdef CONFIG_SND_HDA_POWER_SAVE
4207 if (!spec->loopback.amplist)
4208 spec->loopback.amplist = alc882_loopbacks;
4209#endif
4210
4211 return 0;
4212}
4213
4214
4215/*
4216 * ALC262 support
4217 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004218static int alc262_parse_auto_config(struct hda_codec *codec)
4219{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004220 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004221 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4222 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004223}
4224
4225/*
4226 * Pin config fixes
4227 */
4228enum {
4229 PINFIX_FSC_H270,
4230 PINFIX_HP_Z200,
4231};
4232
4233static const struct alc_fixup alc262_fixups[] = {
4234 [PINFIX_FSC_H270] = {
4235 .type = ALC_FIXUP_PINS,
4236 .v.pins = (const struct alc_pincfg[]) {
4237 { 0x14, 0x99130110 }, /* speaker */
4238 { 0x15, 0x0221142f }, /* front HP */
4239 { 0x1b, 0x0121141f }, /* rear HP */
4240 { }
4241 }
4242 },
4243 [PINFIX_HP_Z200] = {
4244 .type = ALC_FIXUP_PINS,
4245 .v.pins = (const struct alc_pincfg[]) {
4246 { 0x16, 0x99130120 }, /* internal speaker */
4247 { }
4248 }
4249 },
4250};
4251
4252static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4253 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4254 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4255 {}
4256};
4257
4258
4259#ifdef CONFIG_SND_HDA_POWER_SAVE
4260#define alc262_loopbacks alc880_loopbacks
4261#endif
4262
Takashi Iwai1d045db2011-07-07 18:23:21 +02004263/*
4264 */
4265#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4266#include "alc262_quirks.c"
4267#endif
4268
4269static int patch_alc262(struct hda_codec *codec)
4270{
4271 struct alc_spec *spec;
4272 int board_config;
4273 int err;
4274
4275 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4276 if (spec == NULL)
4277 return -ENOMEM;
4278
4279 codec->spec = spec;
4280
4281 spec->mixer_nid = 0x0b;
4282
4283#if 0
4284 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4285 * under-run
4286 */
4287 {
4288 int tmp;
4289 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4290 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4291 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4292 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4293 }
4294#endif
4295 alc_auto_parse_customize_define(codec);
4296
4297 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4298
4299 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4300 alc262_models, alc262_cfg_tbl);
4301
4302 if (board_config < 0) {
4303 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4304 codec->chip_name);
4305 board_config = ALC_MODEL_AUTO;
4306 }
4307
4308 if (board_config == ALC_MODEL_AUTO) {
4309 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4310 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4311 }
4312
4313 if (board_config == ALC_MODEL_AUTO) {
4314 /* automatic parse from the BIOS config */
4315 err = alc262_parse_auto_config(codec);
4316 if (err < 0) {
4317 alc_free(codec);
4318 return err;
4319 }
4320#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4321 else if (!err) {
4322 printk(KERN_INFO
4323 "hda_codec: Cannot set up configuration "
4324 "from BIOS. Using base mode...\n");
4325 board_config = ALC262_BASIC;
4326 }
4327#endif
4328 }
4329
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004330 if (board_config != ALC_MODEL_AUTO)
4331 setup_preset(codec, &alc262_presets[board_config]);
4332
Takashi Iwai60a6a842011-07-27 14:01:24 +02004333 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004334 alc_auto_fill_adc_caps(codec);
4335 alc_rebuild_imux_for_auto_mic(codec);
4336 alc_remove_invalid_adc_nids(codec);
4337 }
4338
4339 if (!spec->no_analog && !spec->cap_mixer)
4340 set_capture_mixer(codec);
4341
Takashi Iwai1d045db2011-07-07 18:23:21 +02004342 if (!spec->no_analog && has_cdefine_beep(codec)) {
4343 err = snd_hda_attach_beep_device(codec, 0x1);
4344 if (err < 0) {
4345 alc_free(codec);
4346 return err;
4347 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004348 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004349 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004350
4351 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4352
4353 spec->vmaster_nid = 0x0c;
4354
4355 codec->patch_ops = alc_patch_ops;
4356 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004357 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004358 spec->shutup = alc_eapd_shutup;
4359
4360 alc_init_jacks(codec);
4361#ifdef CONFIG_SND_HDA_POWER_SAVE
4362 if (!spec->loopback.amplist)
4363 spec->loopback.amplist = alc262_loopbacks;
4364#endif
4365
4366 return 0;
4367}
4368
4369/*
4370 * ALC268
4371 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004372/* bind Beep switches of both NID 0x0f and 0x10 */
4373static const struct hda_bind_ctls alc268_bind_beep_sw = {
4374 .ops = &snd_hda_bind_sw,
4375 .values = {
4376 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4377 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4378 0
4379 },
4380};
4381
4382static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4383 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4384 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4385 { }
4386};
4387
4388/* set PCBEEP vol = 0, mute connections */
4389static const struct hda_verb alc268_beep_init_verbs[] = {
4390 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4391 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4392 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4393 { }
4394};
4395
4396/*
4397 * BIOS auto configuration
4398 */
4399static int alc268_parse_auto_config(struct hda_codec *codec)
4400{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004401 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004402 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004403 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4404 if (err > 0) {
4405 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4406 add_mixer(spec, alc268_beep_mixer);
4407 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004408 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004409 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004410 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004411}
4412
Takashi Iwai1d045db2011-07-07 18:23:21 +02004413/*
4414 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004415static int patch_alc268(struct hda_codec *codec)
4416{
4417 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004418 int i, has_beep, err;
4419
4420 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4421 if (spec == NULL)
4422 return -ENOMEM;
4423
4424 codec->spec = spec;
4425
4426 /* ALC268 has no aa-loopback mixer */
4427
Takashi Iwai6ebb8052011-08-16 15:15:40 +02004428 /* automatic parse from the BIOS config */
4429 err = alc268_parse_auto_config(codec);
4430 if (err < 0) {
4431 alc_free(codec);
4432 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004433 }
4434
Takashi Iwai1d045db2011-07-07 18:23:21 +02004435 has_beep = 0;
4436 for (i = 0; i < spec->num_mixers; i++) {
4437 if (spec->mixers[i] == alc268_beep_mixer) {
4438 has_beep = 1;
4439 break;
4440 }
4441 }
4442
4443 if (has_beep) {
4444 err = snd_hda_attach_beep_device(codec, 0x1);
4445 if (err < 0) {
4446 alc_free(codec);
4447 return err;
4448 }
4449 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4450 /* override the amp caps for beep generator */
4451 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4452 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4453 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4454 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4455 (0 << AC_AMPCAP_MUTE_SHIFT));
4456 }
4457
Takashi Iwai60a6a842011-07-27 14:01:24 +02004458 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004459 alc_auto_fill_adc_caps(codec);
4460 alc_rebuild_imux_for_auto_mic(codec);
4461 alc_remove_invalid_adc_nids(codec);
4462 }
4463
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004464 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004465 set_capture_mixer(codec);
4466
4467 spec->vmaster_nid = 0x02;
4468
4469 codec->patch_ops = alc_patch_ops;
Takashi Iwai6ebb8052011-08-16 15:15:40 +02004470 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004471 spec->shutup = alc_eapd_shutup;
4472
4473 alc_init_jacks(codec);
4474
4475 return 0;
4476}
4477
4478/*
4479 * ALC269
4480 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004481#ifdef CONFIG_SND_HDA_POWER_SAVE
4482#define alc269_loopbacks alc880_loopbacks
4483#endif
4484
4485static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4486 .substreams = 1,
4487 .channels_min = 2,
4488 .channels_max = 8,
4489 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4490 /* NID is set in alc_build_pcms */
4491 .ops = {
4492 .open = alc_playback_pcm_open,
4493 .prepare = alc_playback_pcm_prepare,
4494 .cleanup = alc_playback_pcm_cleanup
4495 },
4496};
4497
4498static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4499 .substreams = 1,
4500 .channels_min = 2,
4501 .channels_max = 2,
4502 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4503 /* NID is set in alc_build_pcms */
4504};
4505
4506#ifdef CONFIG_SND_HDA_POWER_SAVE
4507static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4508{
4509 switch (codec->subsystem_id) {
4510 case 0x103c1586:
4511 return 1;
4512 }
4513 return 0;
4514}
4515
4516static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4517{
4518 /* update mute-LED according to the speaker mute state */
4519 if (nid == 0x01 || nid == 0x14) {
4520 int pinval;
4521 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4522 HDA_AMP_MUTE)
4523 pinval = 0x24;
4524 else
4525 pinval = 0x20;
4526 /* mic2 vref pin is used for mute LED control */
4527 snd_hda_codec_update_cache(codec, 0x19, 0,
4528 AC_VERB_SET_PIN_WIDGET_CONTROL,
4529 pinval);
4530 }
4531 return alc_check_power_status(codec, nid);
4532}
4533#endif /* CONFIG_SND_HDA_POWER_SAVE */
4534
4535/* different alc269-variants */
4536enum {
4537 ALC269_TYPE_ALC269VA,
4538 ALC269_TYPE_ALC269VB,
4539 ALC269_TYPE_ALC269VC,
4540};
4541
4542/*
4543 * BIOS auto configuration
4544 */
4545static int alc269_parse_auto_config(struct hda_codec *codec)
4546{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004547 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004548 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
4549 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4550 struct alc_spec *spec = codec->spec;
4551 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
4552 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004553
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004554 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004555}
4556
Takashi Iwai1d045db2011-07-07 18:23:21 +02004557static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4558{
4559 int val = alc_read_coef_idx(codec, 0x04);
4560 if (power_up)
4561 val |= 1 << 11;
4562 else
4563 val &= ~(1 << 11);
4564 alc_write_coef_idx(codec, 0x04, val);
4565}
4566
4567static void alc269_shutup(struct hda_codec *codec)
4568{
4569 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4570 alc269_toggle_power_output(codec, 0);
4571 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4572 alc269_toggle_power_output(codec, 0);
4573 msleep(150);
4574 }
4575}
4576
Takashi Iwai2a439522011-07-26 09:52:50 +02004577#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004578static int alc269_resume(struct hda_codec *codec)
4579{
4580 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4581 alc269_toggle_power_output(codec, 0);
4582 msleep(150);
4583 }
4584
4585 codec->patch_ops.init(codec);
4586
4587 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4588 alc269_toggle_power_output(codec, 1);
4589 msleep(200);
4590 }
4591
4592 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4593 alc269_toggle_power_output(codec, 1);
4594
4595 snd_hda_codec_resume_amp(codec);
4596 snd_hda_codec_resume_cache(codec);
4597 hda_call_check_power_status(codec, 0x01);
4598 return 0;
4599}
Takashi Iwai2a439522011-07-26 09:52:50 +02004600#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004601
4602static void alc269_fixup_hweq(struct hda_codec *codec,
4603 const struct alc_fixup *fix, int action)
4604{
4605 int coef;
4606
4607 if (action != ALC_FIXUP_ACT_INIT)
4608 return;
4609 coef = alc_read_coef_idx(codec, 0x1e);
4610 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4611}
4612
4613static void alc271_fixup_dmic(struct hda_codec *codec,
4614 const struct alc_fixup *fix, int action)
4615{
4616 static const struct hda_verb verbs[] = {
4617 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4618 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4619 {}
4620 };
4621 unsigned int cfg;
4622
4623 if (strcmp(codec->chip_name, "ALC271X"))
4624 return;
4625 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4626 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4627 snd_hda_sequence_write(codec, verbs);
4628}
4629
Takashi Iwai017f2a12011-07-09 14:42:25 +02004630static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4631 const struct alc_fixup *fix, int action)
4632{
4633 struct alc_spec *spec = codec->spec;
4634
4635 if (action != ALC_FIXUP_ACT_PROBE)
4636 return;
4637
4638 /* Due to a hardware problem on Lenovo Ideadpad, we need to
4639 * fix the sample rate of analog I/O to 44.1kHz
4640 */
4641 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
4642 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4643}
4644
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004645static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4646 const struct alc_fixup *fix, int action)
4647{
4648 int coef;
4649
4650 if (action != ALC_FIXUP_ACT_INIT)
4651 return;
4652 /* The digital-mic unit sends PDM (differential signal) instead of
4653 * the standard PCM, thus you can't record a valid mono stream as is.
4654 * Below is a workaround specific to ALC269 to control the dmic
4655 * signal source as mono.
4656 */
4657 coef = alc_read_coef_idx(codec, 0x07);
4658 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4659}
4660
Takashi Iwai24519912011-08-16 15:08:49 +02004661static void alc269_quanta_automute(struct hda_codec *codec)
4662{
David Henningsson42cf0d02011-09-20 12:04:56 +02004663 update_outputs(codec);
Takashi Iwai24519912011-08-16 15:08:49 +02004664
4665 snd_hda_codec_write(codec, 0x20, 0,
4666 AC_VERB_SET_COEF_INDEX, 0x0c);
4667 snd_hda_codec_write(codec, 0x20, 0,
4668 AC_VERB_SET_PROC_COEF, 0x680);
4669
4670 snd_hda_codec_write(codec, 0x20, 0,
4671 AC_VERB_SET_COEF_INDEX, 0x0c);
4672 snd_hda_codec_write(codec, 0x20, 0,
4673 AC_VERB_SET_PROC_COEF, 0x480);
4674}
4675
4676static void alc269_fixup_quanta_mute(struct hda_codec *codec,
4677 const struct alc_fixup *fix, int action)
4678{
4679 struct alc_spec *spec = codec->spec;
4680 if (action != ALC_FIXUP_ACT_PROBE)
4681 return;
4682 spec->automute_hook = alc269_quanta_automute;
4683}
4684
Takashi Iwai1d045db2011-07-07 18:23:21 +02004685enum {
4686 ALC269_FIXUP_SONY_VAIO,
4687 ALC275_FIXUP_SONY_VAIO_GPIO2,
4688 ALC269_FIXUP_DELL_M101Z,
4689 ALC269_FIXUP_SKU_IGNORE,
4690 ALC269_FIXUP_ASUS_G73JW,
4691 ALC269_FIXUP_LENOVO_EAPD,
4692 ALC275_FIXUP_SONY_HWEQ,
4693 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004694 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004695 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai24519912011-08-16 15:08:49 +02004696 ALC269_FIXUP_QUANTA_MUTE,
4697 ALC269_FIXUP_LIFEBOOK,
Takashi Iwaia4297b52011-08-23 18:40:12 +02004698 ALC269_FIXUP_AMIC,
4699 ALC269_FIXUP_DMIC,
4700 ALC269VB_FIXUP_AMIC,
4701 ALC269VB_FIXUP_DMIC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004702};
4703
4704static const struct alc_fixup alc269_fixups[] = {
4705 [ALC269_FIXUP_SONY_VAIO] = {
4706 .type = ALC_FIXUP_VERBS,
4707 .v.verbs = (const struct hda_verb[]) {
4708 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4709 {}
4710 }
4711 },
4712 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4713 .type = ALC_FIXUP_VERBS,
4714 .v.verbs = (const struct hda_verb[]) {
4715 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4716 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4717 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4718 { }
4719 },
4720 .chained = true,
4721 .chain_id = ALC269_FIXUP_SONY_VAIO
4722 },
4723 [ALC269_FIXUP_DELL_M101Z] = {
4724 .type = ALC_FIXUP_VERBS,
4725 .v.verbs = (const struct hda_verb[]) {
4726 /* Enables internal speaker */
4727 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4728 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4729 {}
4730 }
4731 },
4732 [ALC269_FIXUP_SKU_IGNORE] = {
4733 .type = ALC_FIXUP_SKU,
4734 .v.sku = ALC_FIXUP_SKU_IGNORE,
4735 },
4736 [ALC269_FIXUP_ASUS_G73JW] = {
4737 .type = ALC_FIXUP_PINS,
4738 .v.pins = (const struct alc_pincfg[]) {
4739 { 0x17, 0x99130111 }, /* subwoofer */
4740 { }
4741 }
4742 },
4743 [ALC269_FIXUP_LENOVO_EAPD] = {
4744 .type = ALC_FIXUP_VERBS,
4745 .v.verbs = (const struct hda_verb[]) {
4746 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4747 {}
4748 }
4749 },
4750 [ALC275_FIXUP_SONY_HWEQ] = {
4751 .type = ALC_FIXUP_FUNC,
4752 .v.func = alc269_fixup_hweq,
4753 .chained = true,
4754 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4755 },
4756 [ALC271_FIXUP_DMIC] = {
4757 .type = ALC_FIXUP_FUNC,
4758 .v.func = alc271_fixup_dmic,
4759 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004760 [ALC269_FIXUP_PCM_44K] = {
4761 .type = ALC_FIXUP_FUNC,
4762 .v.func = alc269_fixup_pcm_44k,
4763 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004764 [ALC269_FIXUP_STEREO_DMIC] = {
4765 .type = ALC_FIXUP_FUNC,
4766 .v.func = alc269_fixup_stereo_dmic,
4767 },
Takashi Iwai24519912011-08-16 15:08:49 +02004768 [ALC269_FIXUP_QUANTA_MUTE] = {
4769 .type = ALC_FIXUP_FUNC,
4770 .v.func = alc269_fixup_quanta_mute,
4771 },
4772 [ALC269_FIXUP_LIFEBOOK] = {
4773 .type = ALC_FIXUP_PINS,
4774 .v.pins = (const struct alc_pincfg[]) {
4775 { 0x1a, 0x2101103f }, /* dock line-out */
4776 { 0x1b, 0x23a11040 }, /* dock mic-in */
4777 { }
4778 },
4779 .chained = true,
4780 .chain_id = ALC269_FIXUP_QUANTA_MUTE
4781 },
Takashi Iwaia4297b52011-08-23 18:40:12 +02004782 [ALC269_FIXUP_AMIC] = {
4783 .type = ALC_FIXUP_PINS,
4784 .v.pins = (const struct alc_pincfg[]) {
4785 { 0x14, 0x99130110 }, /* speaker */
4786 { 0x15, 0x0121401f }, /* HP out */
4787 { 0x18, 0x01a19c20 }, /* mic */
4788 { 0x19, 0x99a3092f }, /* int-mic */
4789 { }
4790 },
4791 },
4792 [ALC269_FIXUP_DMIC] = {
4793 .type = ALC_FIXUP_PINS,
4794 .v.pins = (const struct alc_pincfg[]) {
4795 { 0x12, 0x99a3092f }, /* int-mic */
4796 { 0x14, 0x99130110 }, /* speaker */
4797 { 0x15, 0x0121401f }, /* HP out */
4798 { 0x18, 0x01a19c20 }, /* mic */
4799 { }
4800 },
4801 },
4802 [ALC269VB_FIXUP_AMIC] = {
4803 .type = ALC_FIXUP_PINS,
4804 .v.pins = (const struct alc_pincfg[]) {
4805 { 0x14, 0x99130110 }, /* speaker */
4806 { 0x18, 0x01a19c20 }, /* mic */
4807 { 0x19, 0x99a3092f }, /* int-mic */
4808 { 0x21, 0x0121401f }, /* HP out */
4809 { }
4810 },
4811 },
4812 [ALC269_FIXUP_DMIC] = {
4813 .type = ALC_FIXUP_PINS,
4814 .v.pins = (const struct alc_pincfg[]) {
4815 { 0x12, 0x99a3092f }, /* int-mic */
4816 { 0x14, 0x99130110 }, /* speaker */
4817 { 0x18, 0x01a19c20 }, /* mic */
4818 { 0x21, 0x0121401f }, /* HP out */
4819 { }
4820 },
4821 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004822};
4823
4824static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02004825 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004826 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4827 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4828 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4829 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4830 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004831 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4832 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4833 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4834 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4835 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4836 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
Takashi Iwai24519912011-08-16 15:08:49 +02004837 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004838 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4839 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4840 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4841 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4842 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai24519912011-08-16 15:08:49 +02004843 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02004844 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004845 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
Takashi Iwaia4297b52011-08-23 18:40:12 +02004846
4847#if 1
4848 /* Below is a quirk table taken from the old code.
4849 * Basically the device should work as is without the fixup table.
4850 * If BIOS doesn't give a proper info, enable the corresponding
4851 * fixup entry.
4852 */
4853 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
4854 ALC269_FIXUP_AMIC),
4855 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
4856 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC),
4857 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
4858 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
4859 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
4860 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC),
4861 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC),
4862 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC),
4863 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC),
4864 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC),
4865 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC),
4866 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC),
4867 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC),
4868 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC),
4869 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC),
4870 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC),
4871 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC),
4872 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC),
4873 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC),
4874 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC),
4875 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC),
4876 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC),
4877 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC),
4878 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC),
4879 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC),
4880 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC),
4881 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC),
4882 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC),
4883 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC),
4884 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC),
4885 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC),
4886 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC),
4887 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC),
4888 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC),
4889 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC),
4890 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC),
4891 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC),
4892 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC),
4893 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC),
4894 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC),
4895#endif
4896 {}
4897};
4898
4899static const struct alc_model_fixup alc269_fixup_models[] = {
4900 {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
4901 {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
Takashi Iwai1d045db2011-07-07 18:23:21 +02004902 {}
4903};
4904
4905
4906static int alc269_fill_coef(struct hda_codec *codec)
4907{
4908 int val;
4909
4910 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4911 alc_write_coef_idx(codec, 0xf, 0x960b);
4912 alc_write_coef_idx(codec, 0xe, 0x8817);
4913 }
4914
4915 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4916 alc_write_coef_idx(codec, 0xf, 0x960b);
4917 alc_write_coef_idx(codec, 0xe, 0x8814);
4918 }
4919
4920 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4921 val = alc_read_coef_idx(codec, 0x04);
4922 /* Power up output pin */
4923 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4924 }
4925
4926 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4927 val = alc_read_coef_idx(codec, 0xd);
4928 if ((val & 0x0c00) >> 10 != 0x1) {
4929 /* Capless ramp up clock control */
4930 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4931 }
4932 val = alc_read_coef_idx(codec, 0x17);
4933 if ((val & 0x01c0) >> 6 != 0x4) {
4934 /* Class D power on reset */
4935 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4936 }
4937 }
4938
4939 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4940 alc_write_coef_idx(codec, 0xd, val | (1<<14));
4941
4942 val = alc_read_coef_idx(codec, 0x4); /* HP */
4943 alc_write_coef_idx(codec, 0x4, val | (1<<11));
4944
4945 return 0;
4946}
4947
4948/*
4949 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004950static int patch_alc269(struct hda_codec *codec)
4951{
4952 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004953 int err;
4954
4955 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4956 if (spec == NULL)
4957 return -ENOMEM;
4958
4959 codec->spec = spec;
4960
4961 spec->mixer_nid = 0x0b;
4962
4963 alc_auto_parse_customize_define(codec);
4964
4965 if (codec->vendor_id == 0x10ec0269) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004966 unsigned int coef;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004967 spec->codec_variant = ALC269_TYPE_ALC269VA;
4968 coef = alc_read_coef_idx(codec, 0);
4969 if ((coef & 0x00f0) == 0x0010) {
4970 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
4971 spec->cdefine.platform_type == 1) {
4972 alc_codec_rename(codec, "ALC271X");
4973 } else if ((coef & 0xf000) == 0x2000) {
4974 alc_codec_rename(codec, "ALC259");
4975 } else if ((coef & 0xf000) == 0x3000) {
4976 alc_codec_rename(codec, "ALC258");
4977 } else if ((coef & 0xfff0) == 0x3010) {
4978 alc_codec_rename(codec, "ALC277");
4979 } else {
4980 alc_codec_rename(codec, "ALC269VB");
4981 }
4982 spec->codec_variant = ALC269_TYPE_ALC269VB;
4983 } else if ((coef & 0x00f0) == 0x0020) {
4984 if (coef == 0xa023)
4985 alc_codec_rename(codec, "ALC259");
4986 else if (coef == 0x6023)
4987 alc_codec_rename(codec, "ALC281X");
4988 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4989 codec->bus->pci->subsystem_device == 0x21f3)
4990 alc_codec_rename(codec, "ALC3202");
4991 else
4992 alc_codec_rename(codec, "ALC269VC");
4993 spec->codec_variant = ALC269_TYPE_ALC269VC;
4994 } else
4995 alc_fix_pll_init(codec, 0x20, 0x04, 15);
4996 alc269_fill_coef(codec);
4997 }
4998
Takashi Iwaia4297b52011-08-23 18:40:12 +02004999 alc_pick_fixup(codec, alc269_fixup_models,
5000 alc269_fixup_tbl, alc269_fixups);
5001 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005002
Takashi Iwaia4297b52011-08-23 18:40:12 +02005003 /* automatic parse from the BIOS config */
5004 err = alc269_parse_auto_config(codec);
5005 if (err < 0) {
5006 alc_free(codec);
5007 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005008 }
5009
Takashi Iwai60a6a842011-07-27 14:01:24 +02005010 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005011 alc_auto_fill_adc_caps(codec);
5012 alc_rebuild_imux_for_auto_mic(codec);
5013 alc_remove_invalid_adc_nids(codec);
5014 }
5015
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005016 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005017 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005018
5019 if (!spec->no_analog && has_cdefine_beep(codec)) {
5020 err = snd_hda_attach_beep_device(codec, 0x1);
5021 if (err < 0) {
5022 alc_free(codec);
5023 return err;
5024 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005025 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005026 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005027
5028 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5029
5030 spec->vmaster_nid = 0x02;
5031
5032 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02005033#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02005034 codec->patch_ops.resume = alc269_resume;
5035#endif
Takashi Iwaia4297b52011-08-23 18:40:12 +02005036 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005037 spec->shutup = alc269_shutup;
5038
5039 alc_init_jacks(codec);
5040#ifdef CONFIG_SND_HDA_POWER_SAVE
5041 if (!spec->loopback.amplist)
5042 spec->loopback.amplist = alc269_loopbacks;
5043 if (alc269_mic2_for_mute_led(codec))
5044 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
5045#endif
5046
5047 return 0;
5048}
5049
5050/*
5051 * ALC861
5052 */
5053
Takashi Iwai1d045db2011-07-07 18:23:21 +02005054static int alc861_parse_auto_config(struct hda_codec *codec)
5055{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005056 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005057 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
5058 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005059}
5060
Takashi Iwai1d045db2011-07-07 18:23:21 +02005061#ifdef CONFIG_SND_HDA_POWER_SAVE
5062static const struct hda_amp_list alc861_loopbacks[] = {
5063 { 0x15, HDA_INPUT, 0 },
5064 { 0x15, HDA_INPUT, 1 },
5065 { 0x15, HDA_INPUT, 2 },
5066 { 0x15, HDA_INPUT, 3 },
5067 { } /* end */
5068};
5069#endif
5070
5071
5072/* Pin config fixes */
5073enum {
5074 PINFIX_FSC_AMILO_PI1505,
5075};
5076
5077static const struct alc_fixup alc861_fixups[] = {
5078 [PINFIX_FSC_AMILO_PI1505] = {
5079 .type = ALC_FIXUP_PINS,
5080 .v.pins = (const struct alc_pincfg[]) {
5081 { 0x0b, 0x0221101f }, /* HP */
5082 { 0x0f, 0x90170310 }, /* speaker */
5083 { }
5084 }
5085 },
5086};
5087
5088static const struct snd_pci_quirk alc861_fixup_tbl[] = {
5089 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
5090 {}
5091};
5092
5093/*
5094 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005095static int patch_alc861(struct hda_codec *codec)
5096{
5097 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005098 int err;
5099
5100 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5101 if (spec == NULL)
5102 return -ENOMEM;
5103
5104 codec->spec = spec;
5105
5106 spec->mixer_nid = 0x15;
5107
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005108 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
5109 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005110
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005111 /* automatic parse from the BIOS config */
5112 err = alc861_parse_auto_config(codec);
5113 if (err < 0) {
5114 alc_free(codec);
5115 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005116 }
5117
Takashi Iwai60a6a842011-07-27 14:01:24 +02005118 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005119 alc_auto_fill_adc_caps(codec);
5120 alc_rebuild_imux_for_auto_mic(codec);
5121 alc_remove_invalid_adc_nids(codec);
5122 }
5123
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005124 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005125 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005126
5127 if (!spec->no_analog) {
5128 err = snd_hda_attach_beep_device(codec, 0x23);
5129 if (err < 0) {
5130 alc_free(codec);
5131 return err;
5132 }
5133 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
5134 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005135
5136 spec->vmaster_nid = 0x03;
5137
5138 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5139
5140 codec->patch_ops = alc_patch_ops;
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005141 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005142#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005143 spec->power_hook = alc_power_eapd;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005144 if (!spec->loopback.amplist)
5145 spec->loopback.amplist = alc861_loopbacks;
5146#endif
5147
5148 return 0;
5149}
5150
5151/*
5152 * ALC861-VD support
5153 *
5154 * Based on ALC882
5155 *
5156 * In addition, an independent DAC
5157 */
5158#ifdef CONFIG_SND_HDA_POWER_SAVE
5159#define alc861vd_loopbacks alc880_loopbacks
5160#endif
5161
Takashi Iwai1d045db2011-07-07 18:23:21 +02005162static int alc861vd_parse_auto_config(struct hda_codec *codec)
5163{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005164 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005165 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5166 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005167}
5168
Takashi Iwai1d045db2011-07-07 18:23:21 +02005169enum {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005170 ALC660VD_FIX_ASUS_GPIO1,
5171 ALC861VD_FIX_DALLAS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02005172};
5173
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005174/* exclude VREF80 */
5175static void alc861vd_fixup_dallas(struct hda_codec *codec,
5176 const struct alc_fixup *fix, int action)
5177{
5178 if (action == ALC_FIXUP_ACT_PRE_PROBE) {
5179 snd_hda_override_pin_caps(codec, 0x18, 0x00001714);
5180 snd_hda_override_pin_caps(codec, 0x19, 0x0000171c);
5181 }
5182}
5183
Takashi Iwai1d045db2011-07-07 18:23:21 +02005184static const struct alc_fixup alc861vd_fixups[] = {
5185 [ALC660VD_FIX_ASUS_GPIO1] = {
5186 .type = ALC_FIXUP_VERBS,
5187 .v.verbs = (const struct hda_verb[]) {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005188 /* reset GPIO1 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005189 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5190 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5191 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5192 { }
5193 }
5194 },
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005195 [ALC861VD_FIX_DALLAS] = {
5196 .type = ALC_FIXUP_FUNC,
5197 .v.func = alc861vd_fixup_dallas,
5198 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02005199};
5200
5201static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005202 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005203 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005204 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005205 {}
5206};
5207
5208static const struct hda_verb alc660vd_eapd_verbs[] = {
5209 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
5210 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
5211 { }
5212};
5213
5214/*
5215 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005216static int patch_alc861vd(struct hda_codec *codec)
5217{
5218 struct alc_spec *spec;
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005219 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005220
5221 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5222 if (spec == NULL)
5223 return -ENOMEM;
5224
5225 codec->spec = spec;
5226
5227 spec->mixer_nid = 0x0b;
5228
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005229 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
5230 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005231
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005232 /* automatic parse from the BIOS config */
5233 err = alc861vd_parse_auto_config(codec);
5234 if (err < 0) {
5235 alc_free(codec);
5236 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005237 }
5238
Takashi Iwai1d045db2011-07-07 18:23:21 +02005239 if (codec->vendor_id == 0x10ec0660) {
5240 /* always turn on EAPD */
5241 add_verb(spec, alc660vd_eapd_verbs);
5242 }
5243
Takashi Iwai60a6a842011-07-27 14:01:24 +02005244 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005245 alc_auto_fill_adc_caps(codec);
5246 alc_rebuild_imux_for_auto_mic(codec);
5247 alc_remove_invalid_adc_nids(codec);
5248 }
5249
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005250 if (!spec->no_analog && !spec->cap_mixer)
5251 set_capture_mixer(codec);
5252
5253 if (!spec->no_analog) {
5254 err = snd_hda_attach_beep_device(codec, 0x23);
5255 if (err < 0) {
5256 alc_free(codec);
5257 return err;
5258 }
5259 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5260 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005261
5262 spec->vmaster_nid = 0x02;
5263
5264 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5265
5266 codec->patch_ops = alc_patch_ops;
5267
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005268 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005269 spec->shutup = alc_eapd_shutup;
5270#ifdef CONFIG_SND_HDA_POWER_SAVE
5271 if (!spec->loopback.amplist)
5272 spec->loopback.amplist = alc861vd_loopbacks;
5273#endif
5274
5275 return 0;
5276}
5277
5278/*
5279 * ALC662 support
5280 *
5281 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5282 * configuration. Each pin widget can choose any input DACs and a mixer.
5283 * Each ADC is connected from a mixer of all inputs. This makes possible
5284 * 6-channel independent captures.
5285 *
5286 * In addition, an independent DAC for the multi-playback (not used in this
5287 * driver yet).
5288 */
5289#ifdef CONFIG_SND_HDA_POWER_SAVE
5290#define alc662_loopbacks alc880_loopbacks
5291#endif
5292
5293/*
5294 * BIOS auto configuration
5295 */
5296
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005297static int alc662_parse_auto_config(struct hda_codec *codec)
5298{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005299 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005300 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5301 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5302 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005303
Kailang Yang6227cdc2010-02-25 08:36:52 +01005304 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5305 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005306 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005307 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005308 ssids = alc662_ssids;
5309 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005310}
5311
Todd Broch6be79482010-12-07 16:51:05 -08005312static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005313 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005314{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005315 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005316 return;
Todd Broch6be79482010-12-07 16:51:05 -08005317 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5318 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5319 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5320 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5321 (0 << AC_AMPCAP_MUTE_SHIFT)))
5322 printk(KERN_WARNING
5323 "hda_codec: failed to override amp caps for NID 0x2\n");
5324}
5325
David Henningsson6cb3b702010-09-09 08:51:44 +02005326enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005327 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005328 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005329 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005330 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005331 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005332 ALC662_FIXUP_HP_RP5800,
Takashi Iwai53c334a2011-08-23 18:27:14 +02005333 ALC662_FIXUP_ASUS_MODE1,
5334 ALC662_FIXUP_ASUS_MODE2,
5335 ALC662_FIXUP_ASUS_MODE3,
5336 ALC662_FIXUP_ASUS_MODE4,
5337 ALC662_FIXUP_ASUS_MODE5,
5338 ALC662_FIXUP_ASUS_MODE6,
5339 ALC662_FIXUP_ASUS_MODE7,
5340 ALC662_FIXUP_ASUS_MODE8,
David Henningsson6cb3b702010-09-09 08:51:44 +02005341};
5342
5343static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005344 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005345 .type = ALC_FIXUP_PINS,
5346 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005347 { 0x15, 0x99130112 }, /* subwoofer */
5348 { }
5349 }
5350 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005351 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005352 .type = ALC_FIXUP_PINS,
5353 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005354 { 0x17, 0x99130112 }, /* subwoofer */
5355 { }
5356 }
5357 },
Todd Broch6be79482010-12-07 16:51:05 -08005358 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005359 .type = ALC_FIXUP_FUNC,
5360 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005361 },
5362 [ALC662_FIXUP_CZC_P10T] = {
5363 .type = ALC_FIXUP_VERBS,
5364 .v.verbs = (const struct hda_verb[]) {
5365 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5366 {}
5367 }
5368 },
David Henningsson94024cd2011-04-29 14:10:55 +02005369 [ALC662_FIXUP_SKU_IGNORE] = {
5370 .type = ALC_FIXUP_SKU,
5371 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005372 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005373 [ALC662_FIXUP_HP_RP5800] = {
5374 .type = ALC_FIXUP_PINS,
5375 .v.pins = (const struct alc_pincfg[]) {
5376 { 0x14, 0x0221201f }, /* HP out */
5377 { }
5378 },
5379 .chained = true,
5380 .chain_id = ALC662_FIXUP_SKU_IGNORE
5381 },
Takashi Iwai53c334a2011-08-23 18:27:14 +02005382 [ALC662_FIXUP_ASUS_MODE1] = {
5383 .type = ALC_FIXUP_PINS,
5384 .v.pins = (const struct alc_pincfg[]) {
5385 { 0x14, 0x99130110 }, /* speaker */
5386 { 0x18, 0x01a19c20 }, /* mic */
5387 { 0x19, 0x99a3092f }, /* int-mic */
5388 { 0x21, 0x0121401f }, /* HP out */
5389 { }
5390 },
5391 .chained = true,
5392 .chain_id = ALC662_FIXUP_SKU_IGNORE
5393 },
5394 [ALC662_FIXUP_ASUS_MODE2] = {
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005395 .type = ALC_FIXUP_PINS,
5396 .v.pins = (const struct alc_pincfg[]) {
5397 { 0x14, 0x99130110 }, /* speaker */
5398 { 0x18, 0x01a19820 }, /* mic */
5399 { 0x19, 0x99a3092f }, /* int-mic */
5400 { 0x1b, 0x0121401f }, /* HP out */
5401 { }
5402 },
Takashi Iwai53c334a2011-08-23 18:27:14 +02005403 .chained = true,
5404 .chain_id = ALC662_FIXUP_SKU_IGNORE
5405 },
5406 [ALC662_FIXUP_ASUS_MODE3] = {
5407 .type = ALC_FIXUP_PINS,
5408 .v.pins = (const struct alc_pincfg[]) {
5409 { 0x14, 0x99130110 }, /* speaker */
5410 { 0x15, 0x0121441f }, /* HP */
5411 { 0x18, 0x01a19840 }, /* mic */
5412 { 0x19, 0x99a3094f }, /* int-mic */
5413 { 0x21, 0x01211420 }, /* HP2 */
5414 { }
5415 },
5416 .chained = true,
5417 .chain_id = ALC662_FIXUP_SKU_IGNORE
5418 },
5419 [ALC662_FIXUP_ASUS_MODE4] = {
5420 .type = ALC_FIXUP_PINS,
5421 .v.pins = (const struct alc_pincfg[]) {
5422 { 0x14, 0x99130110 }, /* speaker */
5423 { 0x16, 0x99130111 }, /* speaker */
5424 { 0x18, 0x01a19840 }, /* mic */
5425 { 0x19, 0x99a3094f }, /* int-mic */
5426 { 0x21, 0x0121441f }, /* HP */
5427 { }
5428 },
5429 .chained = true,
5430 .chain_id = ALC662_FIXUP_SKU_IGNORE
5431 },
5432 [ALC662_FIXUP_ASUS_MODE5] = {
5433 .type = ALC_FIXUP_PINS,
5434 .v.pins = (const struct alc_pincfg[]) {
5435 { 0x14, 0x99130110 }, /* speaker */
5436 { 0x15, 0x0121441f }, /* HP */
5437 { 0x16, 0x99130111 }, /* speaker */
5438 { 0x18, 0x01a19840 }, /* mic */
5439 { 0x19, 0x99a3094f }, /* int-mic */
5440 { }
5441 },
5442 .chained = true,
5443 .chain_id = ALC662_FIXUP_SKU_IGNORE
5444 },
5445 [ALC662_FIXUP_ASUS_MODE6] = {
5446 .type = ALC_FIXUP_PINS,
5447 .v.pins = (const struct alc_pincfg[]) {
5448 { 0x14, 0x99130110 }, /* speaker */
5449 { 0x15, 0x01211420 }, /* HP2 */
5450 { 0x18, 0x01a19840 }, /* mic */
5451 { 0x19, 0x99a3094f }, /* int-mic */
5452 { 0x1b, 0x0121441f }, /* HP */
5453 { }
5454 },
5455 .chained = true,
5456 .chain_id = ALC662_FIXUP_SKU_IGNORE
5457 },
5458 [ALC662_FIXUP_ASUS_MODE7] = {
5459 .type = ALC_FIXUP_PINS,
5460 .v.pins = (const struct alc_pincfg[]) {
5461 { 0x14, 0x99130110 }, /* speaker */
5462 { 0x17, 0x99130111 }, /* speaker */
5463 { 0x18, 0x01a19840 }, /* mic */
5464 { 0x19, 0x99a3094f }, /* int-mic */
5465 { 0x1b, 0x01214020 }, /* HP */
5466 { 0x21, 0x0121401f }, /* HP */
5467 { }
5468 },
5469 .chained = true,
5470 .chain_id = ALC662_FIXUP_SKU_IGNORE
5471 },
5472 [ALC662_FIXUP_ASUS_MODE8] = {
5473 .type = ALC_FIXUP_PINS,
5474 .v.pins = (const struct alc_pincfg[]) {
5475 { 0x14, 0x99130110 }, /* speaker */
5476 { 0x12, 0x99a30970 }, /* int-mic */
5477 { 0x15, 0x01214020 }, /* HP */
5478 { 0x17, 0x99130111 }, /* speaker */
5479 { 0x18, 0x01a19840 }, /* mic */
5480 { 0x21, 0x0121401f }, /* HP */
5481 { }
5482 },
5483 .chained = true,
5484 .chain_id = ALC662_FIXUP_SKU_IGNORE
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005485 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005486};
5487
Takashi Iwaia9111322011-05-02 11:30:18 +02005488static const struct snd_pci_quirk alc662_fixup_tbl[] = {
Takashi Iwai53c334a2011-08-23 18:27:14 +02005489 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
David Henningssona6c47a82011-02-10 15:39:19 +01005490 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005491 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005492 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005493 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Takashi Iwai53c334a2011-08-23 18:27:14 +02005494 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005495 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005496 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005497 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005498 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
Takashi Iwai53c334a2011-08-23 18:27:14 +02005499
5500#if 0
5501 /* Below is a quirk table taken from the old code.
5502 * Basically the device should work as is without the fixup table.
5503 * If BIOS doesn't give a proper info, enable the corresponding
5504 * fixup entry.
5505 */
5506 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
5507 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
5508 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
5509 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
5510 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5511 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5512 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5513 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
5514 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
5515 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5516 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
5517 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
5518 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
5519 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
5520 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
5521 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5522 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
5523 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
5524 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5525 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5526 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5527 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5528 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
5529 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
5530 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
5531 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5532 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
5533 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5534 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5535 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
5536 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5537 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5538 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
5539 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
5540 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
5541 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
5542 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
5543 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
5544 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
5545 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5546 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
5547 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
5548 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5549 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
5550 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
5551 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
5552 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
5553 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
5554 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5555 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
5556#endif
David Henningsson6cb3b702010-09-09 08:51:44 +02005557 {}
5558};
5559
Todd Broch6be79482010-12-07 16:51:05 -08005560static const struct alc_model_fixup alc662_fixup_models[] = {
5561 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
Takashi Iwai53c334a2011-08-23 18:27:14 +02005562 {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
5563 {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
5564 {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
5565 {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
5566 {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
5567 {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
5568 {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
5569 {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
Todd Broch6be79482010-12-07 16:51:05 -08005570 {}
5571};
David Henningsson6cb3b702010-09-09 08:51:44 +02005572
5573
Takashi Iwai1d045db2011-07-07 18:23:21 +02005574/*
5575 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005576static int patch_alc662(struct hda_codec *codec)
5577{
5578 struct alc_spec *spec;
Takashi Iwaib9c51062011-08-24 18:08:07 +02005579 int err;
Kailang Yang693194f2010-10-21 08:51:48 +02005580 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005581
5582 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5583 if (!spec)
5584 return -ENOMEM;
5585
5586 codec->spec = spec;
5587
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005588 spec->mixer_nid = 0x0b;
5589
Takashi Iwai53c334a2011-08-23 18:27:14 +02005590 /* handle multiple HPs as is */
5591 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
5592
Kailang Yangda00c242010-03-19 11:23:45 +01005593 alc_auto_parse_customize_define(codec);
5594
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005595 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5596
Kailang Yang693194f2010-10-21 08:51:48 +02005597 coef = alc_read_coef_idx(codec, 0);
5598 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005599 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005600 else if (coef & (1 << 14) &&
5601 codec->bus->pci->subsystem_vendor == 0x1025 &&
5602 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005603 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005604 else if (coef == 0x4011)
5605 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005606
Takashi Iwaib9c51062011-08-24 18:08:07 +02005607 alc_pick_fixup(codec, alc662_fixup_models,
5608 alc662_fixup_tbl, alc662_fixups);
5609 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5610 /* automatic parse from the BIOS config */
5611 err = alc662_parse_auto_config(codec);
5612 if (err < 0) {
5613 alc_free(codec);
5614 return err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005615 }
5616
Takashi Iwai60a6a842011-07-27 14:01:24 +02005617 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005618 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005619 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005620 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005621 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005622
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005623 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005624 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005625
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005626 if (!spec->no_analog && has_cdefine_beep(codec)) {
5627 err = snd_hda_attach_beep_device(codec, 0x1);
5628 if (err < 0) {
5629 alc_free(codec);
5630 return err;
5631 }
Kailang Yangda00c242010-03-19 11:23:45 +01005632 switch (codec->vendor_id) {
5633 case 0x10ec0662:
5634 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5635 break;
5636 case 0x10ec0272:
5637 case 0x10ec0663:
5638 case 0x10ec0665:
5639 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5640 break;
5641 case 0x10ec0273:
5642 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5643 break;
5644 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005645 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005646 spec->vmaster_nid = 0x02;
5647
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005648 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5649
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005650 codec->patch_ops = alc_patch_ops;
Takashi Iwaib9c51062011-08-24 18:08:07 +02005651 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c716152011-04-07 10:37:16 +02005652 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005653
Kailang Yangbf1b0222010-10-21 08:49:56 +02005654 alc_init_jacks(codec);
5655
Takashi Iwaicb53c622007-08-10 17:21:45 +02005656#ifdef CONFIG_SND_HDA_POWER_SAVE
5657 if (!spec->loopback.amplist)
5658 spec->loopback.amplist = alc662_loopbacks;
5659#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005660
5661 return 0;
5662}
5663
Kailang Yang274693f2009-12-03 10:07:50 +01005664static int patch_alc888(struct hda_codec *codec)
5665{
5666 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5667 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005668 if (codec->vendor_id == 0x10ec0887)
5669 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5670 else
5671 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005672 if (!codec->chip_name) {
5673 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005674 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005675 }
5676 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005677 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005678 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005679}
5680
Kailang Yangb478b992011-05-18 11:51:15 +02005681static int patch_alc899(struct hda_codec *codec)
5682{
5683 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5684 kfree(codec->chip_name);
5685 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5686 }
5687 return patch_alc882(codec);
5688}
5689
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005690/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005691 * ALC680 support
5692 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005693
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005694static int alc680_parse_auto_config(struct hda_codec *codec)
5695{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005696 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005697}
5698
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005699/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005700 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005701static int patch_alc680(struct hda_codec *codec)
5702{
5703 struct alc_spec *spec;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005704 int err;
5705
5706 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5707 if (spec == NULL)
5708 return -ENOMEM;
5709
5710 codec->spec = spec;
5711
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005712 /* ALC680 has no aa-loopback mixer */
5713
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02005714 /* automatic parse from the BIOS config */
5715 err = alc680_parse_auto_config(codec);
5716 if (err < 0) {
5717 alc_free(codec);
5718 return err;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005719 }
5720
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005721 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005722 set_capture_mixer(codec);
5723
5724 spec->vmaster_nid = 0x02;
5725
5726 codec->patch_ops = alc_patch_ops;
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02005727 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005728
5729 return 0;
5730}
5731
5732/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005733 * patch entries
5734 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005735static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005736 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005737 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005738 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005739 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005740 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005741 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005742 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005743 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005744 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005745 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005746 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005747 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005748 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5749 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5750 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005751 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +02005752 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005753 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5754 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005755 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005756 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005757 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005758 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005759 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005760 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +02005761 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005762 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005763 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005764 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005765 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005766 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005767 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005768 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +02005769 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005770 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai49535502009-06-30 15:28:30 +02005771 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005772 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005773 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005774 {} /* terminator */
5775};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005776
5777MODULE_ALIAS("snd-hda-codec-id:10ec*");
5778
5779MODULE_LICENSE("GPL");
5780MODULE_DESCRIPTION("Realtek HD-audio codec");
5781
5782static struct hda_codec_preset_list realtek_list = {
5783 .preset = snd_hda_preset_realtek,
5784 .owner = THIS_MODULE,
5785};
5786
5787static int __init patch_realtek_init(void)
5788{
5789 return snd_hda_add_codec_preset(&realtek_list);
5790}
5791
5792static void __exit patch_realtek_exit(void)
5793{
5794 snd_hda_delete_codec_preset(&realtek_list);
5795}
5796
5797module_init(patch_realtek_init)
5798module_exit(patch_realtek_exit)