blob: 7a73621a89090e7a7b6bd482bbfd54dafb610722 [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 Woithe7cf51e482006-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 Iwai4953550a2009-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 Iwai1c7161532011-04-07 10:37:16 +0200161 void (*shutup)(struct hda_codec *codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100162
Takashi Iwai834be882006-03-01 14:16:17 +0100163 /* for pin sensing */
Takashi Iwai834be882006-03-01 14:16:17 +0100164 unsigned int jack_present: 1;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200165 unsigned int line_jack_present:1;
Takashi Iwaie9427962011-04-28 15:46:07 +0200166 unsigned int master_mute:1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200167 unsigned int auto_mic:1;
Takashi Iwai21268962011-07-07 15:01:13 +0200168 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
Takashi Iwaid922b512011-04-28 12:18:53 +0200169 unsigned int automute:1; /* HP automute enabled */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200170 unsigned int detect_line:1; /* Line-out detection enabled */
Takashi Iwai8974bd512011-09-19 11:31:34 +0200171 unsigned int automute_lines:1; /* automute line-out as well; NOP when automute_hp_lo isn't set */
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200172 unsigned int automute_hp_lo:1; /* both HP and LO available */
Takashi Iwaicb53c622007-08-10 17:21:45 +0200173
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100174 /* other flags */
175 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai21268962011-07-07 15:01:13 +0200176 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai584c0c42011-03-10 12:51:11 +0100177 unsigned int single_input_src:1;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +0200178 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
Takashi Iwaid922b512011-04-28 12:18:53 +0200179
180 /* auto-mute control */
181 int automute_mode;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200182 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
Takashi Iwaid922b512011-04-28 12:18:53 +0200183
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200184 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200185 int codec_variant; /* flag for other variants */
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100186
Takashi Iwai2134ea42008-01-10 16:53:55 +0100187 /* for virtual master */
188 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200189#ifdef CONFIG_SND_HDA_POWER_SAVE
190 struct hda_loopback_check loopback;
191#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200192
193 /* for PLL fix */
194 hda_nid_t pll_nid;
195 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +0100196
197 /* fix-up list */
198 int fixup_id;
199 const struct alc_fixup *fixup_list;
200 const char *fixup_name;
Takashi Iwaice764ab2011-04-27 16:35:23 +0200201
202 /* multi-io */
203 int multi_ios;
204 struct alc_multi_io multi_io[4];
Kailang Yangdf694da2005-12-05 19:42:22 +0100205};
206
Takashi Iwai1d045db2011-07-07 18:23:21 +0200207#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Takashi Iwai44c02402011-07-08 15:14:19 +0200209static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
210 int dir, unsigned int bits)
211{
212 if (!nid)
213 return false;
214 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
215 if (query_amp_caps(codec, nid, dir) & bits)
216 return true;
217 return false;
218}
219
220#define nid_has_mute(codec, nid, dir) \
221 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
222#define nid_has_volume(codec, nid, dir) \
223 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225/*
226 * input MUX handling
227 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200228static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
229 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230{
231 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
232 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200233 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
234 if (mux_idx >= spec->num_mux_defs)
235 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100236 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
237 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200238 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200241static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
244 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
245 struct alc_spec *spec = codec->spec;
246 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
247
248 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
249 return 0;
250}
251
Takashi Iwai21268962011-07-07 15:01:13 +0200252static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253{
Takashi Iwai21268962011-07-07 15:01:13 +0200254 struct alc_spec *spec = codec->spec;
255 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
256
257 if (spec->cur_adc && spec->cur_adc != new_adc) {
258 /* stream is running, let's swap the current ADC */
259 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
260 spec->cur_adc = new_adc;
261 snd_hda_codec_setup_stream(codec, new_adc,
262 spec->cur_adc_stream_tag, 0,
263 spec->cur_adc_format);
264 return true;
265 }
266 return false;
267}
268
269/* select the given imux item; either unmute exclusively or select the route */
270static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
271 unsigned int idx, bool force)
272{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100274 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100275 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200276 int i, type;
277 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Takashi Iwaicd896c32008-11-18 12:36:33 +0100279 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
280 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100281 if (!imux->num_items && mux_idx > 0)
282 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100283
Takashi Iwai21268962011-07-07 15:01:13 +0200284 if (idx >= imux->num_items)
285 idx = imux->num_items - 1;
286 if (spec->cur_mux[adc_idx] == idx && !force)
287 return 0;
288 spec->cur_mux[adc_idx] = idx;
289
290 if (spec->dyn_adc_switch) {
291 alc_dyn_adc_pcm_resetup(codec, idx);
292 adc_idx = spec->dyn_adc_idx[idx];
293 }
294
295 nid = spec->capsrc_nids ?
296 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
297
298 /* no selection? */
299 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
300 return 1;
301
Takashi Iwaia22d5432009-07-27 12:54:26 +0200302 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200303 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100304 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100305 for (i = 0; i < imux->num_items; i++) {
306 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
307 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
308 imux->items[i].index,
309 HDA_AMP_MUTE, v);
310 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100311 } else {
312 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200313 snd_hda_codec_write_cache(codec, nid, 0,
314 AC_VERB_SET_CONNECT_SEL,
315 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100316 }
Takashi Iwai21268962011-07-07 15:01:13 +0200317 return 1;
318}
319
320static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
321 struct snd_ctl_elem_value *ucontrol)
322{
323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
324 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
325 return alc_mux_select(codec, adc_idx,
326 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100327}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100330 * set up the input pin config (depending on the given auto-pin type)
331 */
332static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
333 int auto_pin_type)
334{
335 unsigned int val = PIN_IN;
336
Takashi Iwai86e29592010-09-09 14:50:17 +0200337 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100338 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200339 unsigned int oldval;
340 oldval = snd_hda_codec_read(codec, nid, 0,
341 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100342 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100343 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200344 /* if the default pin setup is vref50, we give it priority */
345 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100346 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200347 else if (pincap & AC_PINCAP_VREF_50)
348 val = PIN_VREF50;
349 else if (pincap & AC_PINCAP_VREF_100)
350 val = PIN_VREF100;
351 else if (pincap & AC_PINCAP_VREF_GRD)
352 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100353 }
354 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
355}
356
357/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200358 * Append the given mixer and verb elements for the later use
359 * The mixer array is referred in build_controls(), and init_verbs are
360 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100361 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200362static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100363{
364 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
365 return;
366 spec->mixers[spec->num_mixers++] = mix;
367}
368
369static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
370{
371 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
372 return;
373 spec->init_verbs[spec->num_init_verbs++] = verb;
374}
375
376/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200377 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100378 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200379/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200380static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200381 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
382 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
383 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
384 { }
385};
386
Takashi Iwaia9111322011-05-02 11:30:18 +0200387static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200388 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
389 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
390 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
391 { }
392};
393
Takashi Iwaia9111322011-05-02 11:30:18 +0200394static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200395 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
396 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
397 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
398 { }
399};
400
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200401/*
402 * Fix hardware PLL issue
403 * On some codecs, the analog PLL gating control must be off while
404 * the default value is 1.
405 */
406static void alc_fix_pll(struct hda_codec *codec)
407{
408 struct alc_spec *spec = codec->spec;
409 unsigned int val;
410
411 if (!spec->pll_nid)
412 return;
413 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
414 spec->pll_coef_idx);
415 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
416 AC_VERB_GET_PROC_COEF, 0);
417 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
418 spec->pll_coef_idx);
419 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
420 val & ~(1 << spec->pll_coef_bit));
421}
422
423static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
424 unsigned int coef_idx, unsigned int coef_bit)
425{
426 struct alc_spec *spec = codec->spec;
427 spec->pll_nid = nid;
428 spec->pll_coef_idx = coef_idx;
429 spec->pll_coef_bit = coef_bit;
430 alc_fix_pll(codec);
431}
432
Takashi Iwai1d045db2011-07-07 18:23:21 +0200433/*
434 * Jack-reporting via input-jack layer
435 */
436
437/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200438static int alc_init_jacks(struct hda_codec *codec)
439{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100440#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200441 struct alc_spec *spec = codec->spec;
442 int err;
443 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200444 unsigned int mic_nid = spec->ext_mic_pin;
445 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200446
Takashi Iwai265a0242010-09-21 11:26:21 +0200447 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100448 err = snd_hda_input_jack_add(codec, hp_nid,
449 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200450 if (err < 0)
451 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100452 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200453 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200454
Takashi Iwai265a0242010-09-21 11:26:21 +0200455 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100456 err = snd_hda_input_jack_add(codec, mic_nid,
457 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200458 if (err < 0)
459 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100460 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200461 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200462 if (dock_nid) {
463 err = snd_hda_input_jack_add(codec, dock_nid,
464 SND_JACK_MICROPHONE, NULL);
465 if (err < 0)
466 return err;
467 snd_hda_input_jack_report(codec, dock_nid);
468 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100469#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200470 return 0;
471}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200472
Takashi Iwai1d045db2011-07-07 18:23:21 +0200473/*
474 * Jack detections for HP auto-mute and mic-switch
475 */
476
477/* check each pin in the given array; returns true if any of them is plugged */
478static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200479{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200480 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200481
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200482 for (i = 0; i < num_pins; i++) {
483 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200484 if (!nid)
485 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100486 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200487 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200488 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200489 return present;
490}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200491
Takashi Iwai1d045db2011-07-07 18:23:21 +0200492/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200493static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200494 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200495{
496 struct alc_spec *spec = codec->spec;
497 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200498 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200499 int i;
500
501 for (i = 0; i < num_pins; i++) {
502 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200503 if (!nid)
504 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200505 switch (spec->automute_mode) {
506 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200507 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200508 AC_VERB_SET_PIN_WIDGET_CONTROL,
509 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200510 break;
511 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200512 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200513 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200514 break;
515 case ALC_AUTOMUTE_MIXER:
516 nid = spec->automute_mixer_nid[i];
517 if (!nid)
518 break;
519 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200520 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200521 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200522 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200523 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200524 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200525 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200526}
527
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200528/* Toggle internal speakers muting */
529static void update_speakers(struct hda_codec *codec)
530{
531 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200532 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200533
Takashi Iwaic0a20262011-06-10 15:28:15 +0200534 /* Control HP pins/amps depending on master_mute state;
535 * in general, HP pins/amps control should be enabled in all cases,
536 * but currently set only for master_mute, just to be safe
537 */
538 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
539 spec->autocfg.hp_pins, spec->master_mute, true);
540
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200541 if (!spec->automute)
542 on = 0;
543 else
544 on = spec->jack_present | spec->line_jack_present;
545 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200546 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200547 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200548
549 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200550 /* if LO is a copy of either HP or Speaker, don't need to handle it */
551 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
552 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200553 return;
Takashi Iwai8974bd512011-09-19 11:31:34 +0200554 if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200555 on = 0;
556 else
557 on = spec->jack_present;
558 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200559 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200560 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200561}
562
Takashi Iwai1d045db2011-07-07 18:23:21 +0200563/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200564static void alc_hp_automute(struct hda_codec *codec)
565{
566 struct alc_spec *spec = codec->spec;
567
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200568 spec->jack_present =
569 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
570 spec->autocfg.hp_pins);
Takashi Iwai3c715a92011-08-23 12:41:09 +0200571 if (!spec->automute)
572 return;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200573 update_speakers(codec);
574}
575
Takashi Iwai1d045db2011-07-07 18:23:21 +0200576/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200577static void alc_line_automute(struct hda_codec *codec)
578{
579 struct alc_spec *spec = codec->spec;
580
Takashi Iwaie0d32e32011-09-26 15:19:55 +0200581 /* check LO jack only when it's different from HP */
582 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
583 return;
584
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200585 spec->line_jack_present =
586 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
587 spec->autocfg.line_out_pins);
Takashi Iwai3c715a92011-08-23 12:41:09 +0200588 if (!spec->automute || !spec->detect_line)
589 return;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200590 update_speakers(codec);
591}
592
Takashi Iwai8d087c72011-06-28 12:45:47 +0200593#define get_connection_index(codec, mux, nid) \
594 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200595
Takashi Iwai1d045db2011-07-07 18:23:21 +0200596/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200597static void alc_mic_automute(struct hda_codec *codec)
598{
599 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200600 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200601
Takashi Iwai21268962011-07-07 15:01:13 +0200602 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200603 return;
604 if (snd_BUG_ON(!spec->adc_nids))
605 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200606 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200607 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200608
Takashi Iwai21268962011-07-07 15:01:13 +0200609 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
610 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
611 else if (spec->dock_mic_idx >= 0 &&
612 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
613 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
614 else
615 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200616
Takashi Iwai21268962011-07-07 15:01:13 +0200617 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
618 if (spec->dock_mic_idx >= 0)
619 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200620}
621
Kailang Yangc9b58002007-10-16 14:30:01 +0200622/* unsolicited event for HP jack sensing */
623static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
624{
625 if (codec->vendor_id == 0x10ec0880)
626 res >>= 28;
627 else
628 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200629 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200630 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200631 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200632 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200633 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200634 alc_line_automute(codec);
635 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200636 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200637 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200638 break;
639 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200640}
641
Takashi Iwai1d045db2011-07-07 18:23:21 +0200642/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200643static void alc_inithook(struct hda_codec *codec)
644{
Takashi Iwaid922b512011-04-28 12:18:53 +0200645 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200646 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200647 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200648}
649
Kailang Yangf9423e72008-05-27 12:32:25 +0200650/* additional initialization for ALC888 variants */
651static void alc888_coef_init(struct hda_codec *codec)
652{
653 unsigned int tmp;
654
655 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
656 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
657 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100658 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200659 /* alc888S-VC */
660 snd_hda_codec_read(codec, 0x20, 0,
661 AC_VERB_SET_PROC_COEF, 0x830);
662 else
663 /* alc888-VB */
664 snd_hda_codec_read(codec, 0x20, 0,
665 AC_VERB_SET_PROC_COEF, 0x3030);
666}
667
Takashi Iwai1d045db2011-07-07 18:23:21 +0200668/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200669static void alc889_coef_init(struct hda_codec *codec)
670{
671 unsigned int tmp;
672
673 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
674 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
675 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
676 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
677}
678
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100679/* turn on/off EAPD control (only if available) */
680static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
681{
682 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
683 return;
684 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
685 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
686 on ? 2 : 0);
687}
688
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200689/* turn on/off EAPD controls of the codec */
690static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
691{
692 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200693 static hda_nid_t pins[] = {
694 0x0f, 0x10, 0x14, 0x15, 0
695 };
696 hda_nid_t *p;
697 for (p = pins; *p; p++)
698 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200699}
700
Takashi Iwai1c7161532011-04-07 10:37:16 +0200701/* generic shutup callback;
702 * just turning off EPAD and a little pause for avoiding pop-noise
703 */
704static void alc_eapd_shutup(struct hda_codec *codec)
705{
706 alc_auto_setup_eapd(codec, false);
707 msleep(200);
708}
709
Takashi Iwai1d045db2011-07-07 18:23:21 +0200710/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200711static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200712{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200713 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200714
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200715 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200716 switch (type) {
717 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200718 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
719 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200720 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200721 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
722 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200723 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200724 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
725 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200726 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200727 switch (codec->vendor_id) {
728 case 0x10ec0260:
729 snd_hda_codec_write(codec, 0x1a, 0,
730 AC_VERB_SET_COEF_INDEX, 7);
731 tmp = snd_hda_codec_read(codec, 0x1a, 0,
732 AC_VERB_GET_PROC_COEF, 0);
733 snd_hda_codec_write(codec, 0x1a, 0,
734 AC_VERB_SET_COEF_INDEX, 7);
735 snd_hda_codec_write(codec, 0x1a, 0,
736 AC_VERB_SET_PROC_COEF,
737 tmp | 0x2010);
738 break;
739 case 0x10ec0262:
740 case 0x10ec0880:
741 case 0x10ec0882:
742 case 0x10ec0883:
743 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100744 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100745 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200746 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200747 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200748 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200749 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200750 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100751#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200752 case 0x10ec0267:
753 case 0x10ec0268:
754 snd_hda_codec_write(codec, 0x20, 0,
755 AC_VERB_SET_COEF_INDEX, 7);
756 tmp = snd_hda_codec_read(codec, 0x20, 0,
757 AC_VERB_GET_PROC_COEF, 0);
758 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200759 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200760 snd_hda_codec_write(codec, 0x20, 0,
761 AC_VERB_SET_PROC_COEF,
762 tmp | 0x3000);
763 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100764#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200765 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200766 break;
767 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200768}
Kailang Yangea1fb292008-08-26 12:58:38 +0200769
Takashi Iwai1d045db2011-07-07 18:23:21 +0200770/*
771 * Auto-Mute mode mixer enum support
772 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200773static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
774 struct snd_ctl_elem_info *uinfo)
775{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200776 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
777 struct alc_spec *spec = codec->spec;
778 static const char * const texts2[] = {
779 "Disabled", "Enabled"
780 };
781 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200782 "Disabled", "Speaker Only", "Line-Out+Speaker"
783 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200784 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200785
786 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
787 uinfo->count = 1;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200788 if (spec->automute_hp_lo) {
789 uinfo->value.enumerated.items = 3;
790 texts = texts3;
791 } else {
792 uinfo->value.enumerated.items = 2;
793 texts = texts2;
794 }
795 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
796 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200797 strcpy(uinfo->value.enumerated.name,
798 texts[uinfo->value.enumerated.item]);
799 return 0;
800}
801
802static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
803 struct snd_ctl_elem_value *ucontrol)
804{
805 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
806 struct alc_spec *spec = codec->spec;
807 unsigned int val;
808 if (!spec->automute)
809 val = 0;
Takashi Iwai8974bd512011-09-19 11:31:34 +0200810 else if (!spec->automute_hp_lo || !spec->automute_lines)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200811 val = 1;
812 else
813 val = 2;
814 ucontrol->value.enumerated.item[0] = val;
815 return 0;
816}
817
818static int alc_automute_mode_put(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;
823
824 switch (ucontrol->value.enumerated.item[0]) {
825 case 0:
826 if (!spec->automute)
827 return 0;
828 spec->automute = 0;
829 break;
830 case 1:
Takashi Iwai8974bd512011-09-19 11:31:34 +0200831 if (spec->automute &&
832 (!spec->automute_hp_lo || !spec->automute_lines))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200833 return 0;
834 spec->automute = 1;
835 spec->automute_lines = 0;
836 break;
837 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200838 if (!spec->automute_hp_lo)
839 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200840 if (spec->automute && spec->automute_lines)
841 return 0;
842 spec->automute = 1;
843 spec->automute_lines = 1;
844 break;
845 default:
846 return -EINVAL;
847 }
848 update_speakers(codec);
849 return 1;
850}
851
Takashi Iwaia9111322011-05-02 11:30:18 +0200852static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200853 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
854 .name = "Auto-Mute Mode",
855 .info = alc_automute_mode_info,
856 .get = alc_automute_mode_get,
857 .put = alc_automute_mode_put,
858};
859
Takashi Iwai1d045db2011-07-07 18:23:21 +0200860static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
861{
862 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
863 return snd_array_new(&spec->kctls);
864}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200865
866static int alc_add_automute_mode_enum(struct hda_codec *codec)
867{
868 struct alc_spec *spec = codec->spec;
869 struct snd_kcontrol_new *knew;
870
871 knew = alc_kcontrol_new(spec);
872 if (!knew)
873 return -ENOMEM;
874 *knew = alc_automute_mode_enum;
875 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
876 if (!knew->name)
877 return -ENOMEM;
878 return 0;
879}
880
Takashi Iwai1d045db2011-07-07 18:23:21 +0200881/*
882 * Check the availability of HP/line-out auto-mute;
883 * Set up appropriately if really supported
884 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200885static void alc_init_auto_hp(struct hda_codec *codec)
886{
887 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200888 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200889 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200890 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200891
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200892 if (cfg->hp_pins[0])
893 present++;
894 if (cfg->line_out_pins[0])
895 present++;
896 if (cfg->speaker_pins[0])
897 present++;
898 if (present < 2) /* need two different output types */
899 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200900 if (present == 3)
901 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200902
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200903 if (!cfg->speaker_pins[0] &&
904 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200905 memcpy(cfg->speaker_pins, cfg->line_out_pins,
906 sizeof(cfg->speaker_pins));
907 cfg->speaker_outs = cfg->line_outs;
908 }
909
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200910 if (!cfg->hp_pins[0] &&
911 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200912 memcpy(cfg->hp_pins, cfg->line_out_pins,
913 sizeof(cfg->hp_pins));
914 cfg->hp_outs = cfg->line_outs;
915 }
916
917 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200918 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200919 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200920 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200921 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200922 nid);
923 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200924 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200925 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200926 spec->automute = 1;
927 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200928 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200929 if (spec->automute && cfg->line_out_pins[0] &&
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200930 cfg->speaker_pins[0] &&
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200931 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
932 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
933 for (i = 0; i < cfg->line_outs; i++) {
934 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200935 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200936 continue;
937 snd_printdd("realtek: Enable Line-Out auto-muting "
938 "on NID 0x%x\n", nid);
939 snd_hda_codec_write_cache(codec, nid, 0,
940 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200941 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200942 spec->detect_line = 1;
943 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200944 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200945 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200946
947 if (spec->automute) {
948 /* create a control for automute mode */
949 alc_add_automute_mode_enum(codec);
950 spec->unsol_event = alc_sku_unsol_event;
951 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200952}
953
Takashi Iwai1d045db2011-07-07 18:23:21 +0200954/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200955static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
956{
957 int i;
958 for (i = 0; i < nums; i++)
959 if (list[i] == nid)
960 return i;
961 return -1;
962}
963
Takashi Iwai1d045db2011-07-07 18:23:21 +0200964/* check whether dynamic ADC-switching is available */
965static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
966{
967 struct alc_spec *spec = codec->spec;
968 struct hda_input_mux *imux = &spec->private_imux[0];
969 int i, n, idx;
970 hda_nid_t cap, pin;
971
972 if (imux != spec->input_mux) /* no dynamic imux? */
973 return false;
974
975 for (n = 0; n < spec->num_adc_nids; n++) {
976 cap = spec->private_capsrc_nids[n];
977 for (i = 0; i < imux->num_items; i++) {
978 pin = spec->imux_pins[i];
979 if (!pin)
980 return false;
981 if (get_connection_index(codec, cap, pin) < 0)
982 break;
983 }
984 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +0200985 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +0200986 }
987
988 for (i = 0; i < imux->num_items; i++) {
989 pin = spec->imux_pins[i];
990 for (n = 0; n < spec->num_adc_nids; n++) {
991 cap = spec->private_capsrc_nids[n];
992 idx = get_connection_index(codec, cap, pin);
993 if (idx >= 0) {
994 imux->items[i].index = idx;
995 spec->dyn_adc_idx[i] = n;
996 break;
997 }
998 }
999 }
1000
1001 snd_printdd("realtek: enabling ADC switching\n");
1002 spec->dyn_adc_switch = 1;
1003 return true;
1004}
Takashi Iwai21268962011-07-07 15:01:13 +02001005
1006/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1007static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1008{
1009 struct alc_spec *spec = codec->spec;
1010 struct hda_input_mux *imux;
1011 static char * const texts[3] = {
1012 "Mic", "Internal Mic", "Dock Mic"
1013 };
1014 int i;
1015
1016 if (!spec->auto_mic)
1017 return false;
1018 imux = &spec->private_imux[0];
1019 if (spec->input_mux == imux)
1020 return true;
1021 spec->imux_pins[0] = spec->ext_mic_pin;
1022 spec->imux_pins[1] = spec->int_mic_pin;
1023 spec->imux_pins[2] = spec->dock_mic_pin;
1024 for (i = 0; i < 3; i++) {
1025 strcpy(imux->items[i].label, texts[i]);
1026 if (spec->imux_pins[i])
1027 imux->num_items = i + 1;
1028 }
1029 spec->num_mux_defs = 1;
1030 spec->input_mux = imux;
1031 return true;
1032}
1033
1034/* check whether all auto-mic pins are valid; setup indices if OK */
1035static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1036{
1037 struct alc_spec *spec = codec->spec;
1038 const struct hda_input_mux *imux;
1039
1040 if (!spec->auto_mic)
1041 return false;
1042 if (spec->auto_mic_valid_imux)
1043 return true; /* already checked */
1044
1045 /* fill up imux indices */
1046 if (!alc_check_dyn_adc_switch(codec)) {
1047 spec->auto_mic = 0;
1048 return false;
1049 }
1050
1051 imux = spec->input_mux;
1052 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1053 spec->imux_pins, imux->num_items);
1054 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1055 spec->imux_pins, imux->num_items);
1056 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1057 spec->imux_pins, imux->num_items);
1058 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1059 spec->auto_mic = 0;
1060 return false; /* no corresponding imux */
1061 }
1062
1063 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1064 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001065 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001066 if (spec->dock_mic_pin)
1067 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1068 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001069 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001070
1071 spec->auto_mic_valid_imux = 1;
1072 spec->auto_mic = 1;
1073 return true;
1074}
1075
Takashi Iwai1d045db2011-07-07 18:23:21 +02001076/*
1077 * Check the availability of auto-mic switch;
1078 * Set up if really supported
1079 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001080static void alc_init_auto_mic(struct hda_codec *codec)
1081{
1082 struct alc_spec *spec = codec->spec;
1083 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001084 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001085 int i;
1086
Takashi Iwai21268962011-07-07 15:01:13 +02001087 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1088
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001089 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001090 for (i = 0; i < cfg->num_inputs; i++) {
1091 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001092 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001093 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001094 switch (snd_hda_get_input_pin_attr(defcfg)) {
1095 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001096 if (fixed)
1097 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001098 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1099 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001100 fixed = nid;
1101 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001102 case INPUT_PIN_ATTR_UNUSED:
1103 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001104 case INPUT_PIN_ATTR_DOCK:
1105 if (dock)
1106 return; /* already occupied */
1107 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1108 return; /* invalid type */
1109 dock = nid;
1110 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001111 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001112 if (ext)
1113 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001114 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1115 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001116 ext = nid;
1117 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001118 }
1119 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001120 if (!ext && dock) {
1121 ext = dock;
1122 dock = 0;
1123 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001124 if (!ext || !fixed)
1125 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001126 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001127 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001128 if (dock && !is_jack_detectable(codec, dock))
1129 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001130
1131 /* check imux indices */
1132 spec->ext_mic_pin = ext;
1133 spec->int_mic_pin = fixed;
1134 spec->dock_mic_pin = dock;
1135
1136 spec->auto_mic = 1;
1137 if (!alc_auto_mic_check_imux(codec))
1138 return;
1139
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001140 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1141 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001142 spec->unsol_event = alc_sku_unsol_event;
1143}
1144
Takashi Iwai1d045db2011-07-07 18:23:21 +02001145/* check the availabilities of auto-mute and auto-mic switches */
1146static void alc_auto_check_switches(struct hda_codec *codec)
1147{
1148 alc_init_auto_hp(codec);
1149 alc_init_auto_mic(codec);
1150}
1151
1152/*
1153 * Realtek SSID verification
1154 */
1155
David Henningsson90622912010-10-14 14:50:18 +02001156/* Could be any non-zero and even value. When used as fixup, tells
1157 * the driver to ignore any present sku defines.
1158 */
1159#define ALC_FIXUP_SKU_IGNORE (2)
1160
Kailang Yangda00c242010-03-19 11:23:45 +01001161static int alc_auto_parse_customize_define(struct hda_codec *codec)
1162{
1163 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001164 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001165 struct alc_spec *spec = codec->spec;
1166
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001167 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1168
David Henningsson90622912010-10-14 14:50:18 +02001169 if (spec->cdefine.fixup) {
1170 ass = spec->cdefine.sku_cfg;
1171 if (ass == ALC_FIXUP_SKU_IGNORE)
1172 return -1;
1173 goto do_sku;
1174 }
1175
Kailang Yangda00c242010-03-19 11:23:45 +01001176 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001177 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001178 goto do_sku;
1179
1180 nid = 0x1d;
1181 if (codec->vendor_id == 0x10ec0260)
1182 nid = 0x17;
1183 ass = snd_hda_codec_get_pincfg(codec, nid);
1184
1185 if (!(ass & 1)) {
1186 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1187 codec->chip_name, ass);
1188 return -1;
1189 }
1190
1191 /* check sum */
1192 tmp = 0;
1193 for (i = 1; i < 16; i++) {
1194 if ((ass >> i) & 1)
1195 tmp++;
1196 }
1197 if (((ass >> 16) & 0xf) != tmp)
1198 return -1;
1199
1200 spec->cdefine.port_connectivity = ass >> 30;
1201 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1202 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1203 spec->cdefine.customization = ass >> 8;
1204do_sku:
1205 spec->cdefine.sku_cfg = ass;
1206 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1207 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1208 spec->cdefine.swap = (ass & 0x2) >> 1;
1209 spec->cdefine.override = ass & 0x1;
1210
1211 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1212 nid, spec->cdefine.sku_cfg);
1213 snd_printd("SKU: port_connectivity=0x%x\n",
1214 spec->cdefine.port_connectivity);
1215 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1216 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1217 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1218 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1219 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1220 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1221 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1222
1223 return 0;
1224}
1225
Takashi Iwai1d045db2011-07-07 18:23:21 +02001226/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001227static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1228{
Takashi Iwai21268962011-07-07 15:01:13 +02001229 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001230}
1231
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001232/* check subsystem ID and set up device-specific initialization;
1233 * return 1 if initialized, 0 if invalid SSID
1234 */
1235/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1236 * 31 ~ 16 : Manufacture ID
1237 * 15 ~ 8 : SKU ID
1238 * 7 ~ 0 : Assembly ID
1239 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1240 */
1241static int alc_subsystem_id(struct hda_codec *codec,
1242 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001243 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001244{
1245 unsigned int ass, tmp, i;
1246 unsigned nid;
1247 struct alc_spec *spec = codec->spec;
1248
David Henningsson90622912010-10-14 14:50:18 +02001249 if (spec->cdefine.fixup) {
1250 ass = spec->cdefine.sku_cfg;
1251 if (ass == ALC_FIXUP_SKU_IGNORE)
1252 return 0;
1253 goto do_sku;
1254 }
1255
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001256 ass = codec->subsystem_id & 0xffff;
1257 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1258 goto do_sku;
1259
1260 /* invalid SSID, check the special NID pin defcfg instead */
1261 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001262 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001263 * 29~21 : reserve
1264 * 20 : PCBEEP input
1265 * 19~16 : Check sum (15:1)
1266 * 15~1 : Custom
1267 * 0 : override
1268 */
1269 nid = 0x1d;
1270 if (codec->vendor_id == 0x10ec0260)
1271 nid = 0x17;
1272 ass = snd_hda_codec_get_pincfg(codec, nid);
1273 snd_printd("realtek: No valid SSID, "
1274 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001275 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001276 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001277 return 0;
1278 if ((ass >> 30) != 1) /* no physical connection */
1279 return 0;
1280
1281 /* check sum */
1282 tmp = 0;
1283 for (i = 1; i < 16; i++) {
1284 if ((ass >> i) & 1)
1285 tmp++;
1286 }
1287 if (((ass >> 16) & 0xf) != tmp)
1288 return 0;
1289do_sku:
1290 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1291 ass & 0xffff, codec->vendor_id);
1292 /*
1293 * 0 : override
1294 * 1 : Swap Jack
1295 * 2 : 0 --> Desktop, 1 --> Laptop
1296 * 3~5 : External Amplifier control
1297 * 7~6 : Reserved
1298 */
1299 tmp = (ass & 0x38) >> 3; /* external Amp control */
1300 switch (tmp) {
1301 case 1:
1302 spec->init_amp = ALC_INIT_GPIO1;
1303 break;
1304 case 3:
1305 spec->init_amp = ALC_INIT_GPIO2;
1306 break;
1307 case 7:
1308 spec->init_amp = ALC_INIT_GPIO3;
1309 break;
1310 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001311 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001312 spec->init_amp = ALC_INIT_DEFAULT;
1313 break;
1314 }
1315
1316 /* is laptop or Desktop and enable the function "Mute internal speaker
1317 * when the external headphone out jack is plugged"
1318 */
1319 if (!(ass & 0x8000))
1320 return 1;
1321 /*
1322 * 10~8 : Jack location
1323 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1324 * 14~13: Resvered
1325 * 15 : 1 --> enable the function "Mute internal speaker
1326 * when the external headphone out jack is plugged"
1327 */
Takashi Iwai5fe6e012011-09-26 10:41:21 +02001328 if (!spec->autocfg.hp_pins[0] &&
1329 !(spec->autocfg.line_out_pins[0] &&
1330 spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001331 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001332 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1333 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001334 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001335 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001336 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001337 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001338 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001339 else if (tmp == 3)
1340 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001341 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001342 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001343 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1344 spec->autocfg.line_outs))
1345 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001346 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001347 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001348 return 1;
1349}
Kailang Yangea1fb292008-08-26 12:58:38 +02001350
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001351/* Check the validity of ALC subsystem-id
1352 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1353static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001354{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001355 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001356 struct alc_spec *spec = codec->spec;
1357 snd_printd("realtek: "
1358 "Enable default setup for auto mode as fallback\n");
1359 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001360 }
Takashi Iwai21268962011-07-07 15:01:13 +02001361}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001362
Takashi Iwai41e41f12005-06-08 14:48:49 +02001363/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001364 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001365 */
1366
1367struct alc_pincfg {
1368 hda_nid_t nid;
1369 u32 val;
1370};
1371
Todd Broche1eb5f12010-12-06 11:19:51 -08001372struct alc_model_fixup {
1373 const int id;
1374 const char *name;
1375};
1376
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001377struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001378 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001379 bool chained;
1380 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001381 union {
1382 unsigned int sku;
1383 const struct alc_pincfg *pins;
1384 const struct hda_verb *verbs;
1385 void (*func)(struct hda_codec *codec,
1386 const struct alc_fixup *fix,
1387 int action);
1388 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001389};
1390
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001391enum {
1392 ALC_FIXUP_INVALID,
1393 ALC_FIXUP_SKU,
1394 ALC_FIXUP_PINS,
1395 ALC_FIXUP_VERBS,
1396 ALC_FIXUP_FUNC,
1397};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001398
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001399enum {
1400 ALC_FIXUP_ACT_PRE_PROBE,
1401 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001402 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001403};
1404
1405static void alc_apply_fixup(struct hda_codec *codec, int action)
1406{
1407 struct alc_spec *spec = codec->spec;
1408 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001409#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001410 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001411#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001412 int depth = 0;
1413
1414 if (!spec->fixup_list)
1415 return;
1416
1417 while (id >= 0) {
1418 const struct alc_fixup *fix = spec->fixup_list + id;
1419 const struct alc_pincfg *cfg;
1420
1421 switch (fix->type) {
1422 case ALC_FIXUP_SKU:
1423 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1424 break;;
1425 snd_printdd(KERN_INFO "hda_codec: %s: "
1426 "Apply sku override for %s\n",
1427 codec->chip_name, modelname);
1428 spec->cdefine.sku_cfg = fix->v.sku;
1429 spec->cdefine.fixup = 1;
1430 break;
1431 case ALC_FIXUP_PINS:
1432 cfg = fix->v.pins;
1433 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1434 break;
1435 snd_printdd(KERN_INFO "hda_codec: %s: "
1436 "Apply pincfg for %s\n",
1437 codec->chip_name, modelname);
1438 for (; cfg->nid; cfg++)
1439 snd_hda_codec_set_pincfg(codec, cfg->nid,
1440 cfg->val);
1441 break;
1442 case ALC_FIXUP_VERBS:
1443 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1444 break;
1445 snd_printdd(KERN_INFO "hda_codec: %s: "
1446 "Apply fix-verbs for %s\n",
1447 codec->chip_name, modelname);
1448 add_verb(codec->spec, fix->v.verbs);
1449 break;
1450 case ALC_FIXUP_FUNC:
1451 if (!fix->v.func)
1452 break;
1453 snd_printdd(KERN_INFO "hda_codec: %s: "
1454 "Apply fix-func for %s\n",
1455 codec->chip_name, modelname);
1456 fix->v.func(codec, fix, action);
1457 break;
1458 default:
1459 snd_printk(KERN_ERR "hda_codec: %s: "
1460 "Invalid fixup type %d\n",
1461 codec->chip_name, fix->type);
1462 break;
1463 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001464 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001465 break;
1466 if (++depth > 10)
1467 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001468 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001469 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001470}
1471
Todd Broche1eb5f12010-12-06 11:19:51 -08001472static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001473 const struct alc_model_fixup *models,
1474 const struct snd_pci_quirk *quirk,
1475 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001476{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001477 struct alc_spec *spec = codec->spec;
1478 int id = -1;
1479 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001480
Todd Broche1eb5f12010-12-06 11:19:51 -08001481 if (codec->modelname && models) {
1482 while (models->name) {
1483 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001484 id = models->id;
1485 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001486 break;
1487 }
1488 models++;
1489 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001490 }
1491 if (id < 0) {
1492 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1493 if (quirk) {
1494 id = quirk->value;
1495#ifdef CONFIG_SND_DEBUG_VERBOSE
1496 name = quirk->name;
1497#endif
1498 }
1499 }
1500
1501 spec->fixup_id = id;
1502 if (id >= 0) {
1503 spec->fixup_list = fixlist;
1504 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001505 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001506}
1507
Takashi Iwai1d045db2011-07-07 18:23:21 +02001508/*
1509 * COEF access helper functions
1510 */
Kailang Yang274693f2009-12-03 10:07:50 +01001511static int alc_read_coef_idx(struct hda_codec *codec,
1512 unsigned int coef_idx)
1513{
1514 unsigned int val;
1515 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1516 coef_idx);
1517 val = snd_hda_codec_read(codec, 0x20, 0,
1518 AC_VERB_GET_PROC_COEF, 0);
1519 return val;
1520}
1521
Kailang Yang977ddd62010-09-15 10:02:29 +02001522static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1523 unsigned int coef_val)
1524{
1525 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1526 coef_idx);
1527 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1528 coef_val);
1529}
1530
Takashi Iwai1d045db2011-07-07 18:23:21 +02001531/*
1532 * Digital I/O handling
1533 */
1534
Takashi Iwai757899a2010-07-30 10:48:14 +02001535/* set right pin controls for digital I/O */
1536static void alc_auto_init_digital(struct hda_codec *codec)
1537{
1538 struct alc_spec *spec = codec->spec;
1539 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001540 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001541
1542 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1543 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001544 if (!pin)
1545 continue;
1546 snd_hda_codec_write(codec, pin, 0,
1547 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1548 if (!i)
1549 dac = spec->multiout.dig_out_nid;
1550 else
1551 dac = spec->slave_dig_outs[i - 1];
1552 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1553 continue;
1554 snd_hda_codec_write(codec, dac, 0,
1555 AC_VERB_SET_AMP_GAIN_MUTE,
1556 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001557 }
1558 pin = spec->autocfg.dig_in_pin;
1559 if (pin)
1560 snd_hda_codec_write(codec, pin, 0,
1561 AC_VERB_SET_PIN_WIDGET_CONTROL,
1562 PIN_IN);
1563}
1564
1565/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1566static void alc_auto_parse_digital(struct hda_codec *codec)
1567{
1568 struct alc_spec *spec = codec->spec;
1569 int i, err;
1570 hda_nid_t dig_nid;
1571
1572 /* support multiple SPDIFs; the secondary is set up as a slave */
1573 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001574 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001575 err = snd_hda_get_connections(codec,
1576 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001577 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001578 if (err < 0)
1579 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001580 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001581 if (!i) {
1582 spec->multiout.dig_out_nid = dig_nid;
1583 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1584 } else {
1585 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1586 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1587 break;
1588 spec->slave_dig_outs[i - 1] = dig_nid;
1589 }
1590 }
1591
1592 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001593 dig_nid = codec->start_nid;
1594 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1595 unsigned int wcaps = get_wcaps(codec, dig_nid);
1596 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1597 continue;
1598 if (!(wcaps & AC_WCAP_DIGITAL))
1599 continue;
1600 if (!(wcaps & AC_WCAP_CONN_LIST))
1601 continue;
1602 err = get_connection_index(codec, dig_nid,
1603 spec->autocfg.dig_in_pin);
1604 if (err >= 0) {
1605 spec->dig_in_nid = dig_nid;
1606 break;
1607 }
1608 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001609 }
1610}
1611
Takashi Iwaif95474e2007-07-10 00:47:43 +02001612/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001613 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001614 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001615static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1616 struct snd_ctl_elem_info *uinfo)
1617{
1618 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1619 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001620 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001621 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001622
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001623 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001624 if (spec->vol_in_capsrc)
1625 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1626 else
1627 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1628 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001629 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001630 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001631 return err;
1632}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001634static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1635 unsigned int size, unsigned int __user *tlv)
1636{
1637 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1638 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001639 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001640 int err;
1641
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001642 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001643 if (spec->vol_in_capsrc)
1644 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1645 else
1646 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1647 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001648 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001649 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001650 return err;
1651}
1652
1653typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1654 struct snd_ctl_elem_value *ucontrol);
1655
1656static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1657 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001658 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001659{
1660 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1661 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001662 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001663
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001664 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001665 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001666 for (i = 0; i < spec->num_adc_nids; i++) {
1667 kcontrol->private_value =
1668 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1669 3, 0, HDA_INPUT);
1670 err = func(kcontrol, ucontrol);
1671 if (err < 0)
1672 goto error;
1673 }
1674 } else {
1675 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001676 if (spec->vol_in_capsrc)
1677 kcontrol->private_value =
1678 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1679 3, 0, HDA_OUTPUT);
1680 else
1681 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001682 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1683 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001684 err = func(kcontrol, ucontrol);
1685 }
1686 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001687 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001688 return err;
1689}
1690
1691static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1692 struct snd_ctl_elem_value *ucontrol)
1693{
1694 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001695 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001696}
1697
1698static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1699 struct snd_ctl_elem_value *ucontrol)
1700{
1701 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001702 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001703}
1704
1705/* capture mixer elements */
1706#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1707
1708static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1709 struct snd_ctl_elem_value *ucontrol)
1710{
1711 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001712 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001713}
1714
1715static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1716 struct snd_ctl_elem_value *ucontrol)
1717{
1718 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001719 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001720}
1721
Takashi Iwaia23b6882009-03-23 15:21:36 +01001722#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001723 { \
1724 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1725 .name = "Capture Switch", \
1726 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1727 .count = num, \
1728 .info = alc_cap_sw_info, \
1729 .get = alc_cap_sw_get, \
1730 .put = alc_cap_sw_put, \
1731 }, \
1732 { \
1733 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1734 .name = "Capture Volume", \
1735 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1736 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1737 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1738 .count = num, \
1739 .info = alc_cap_vol_info, \
1740 .get = alc_cap_vol_get, \
1741 .put = alc_cap_vol_put, \
1742 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001743 }
1744
1745#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001746 { \
1747 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1748 /* .name = "Capture Source", */ \
1749 .name = "Input Source", \
1750 .count = num, \
1751 .info = alc_mux_enum_info, \
1752 .get = alc_mux_enum_get, \
1753 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001754 }
1755
1756#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001757static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001758 _DEFINE_CAPMIX(num), \
1759 _DEFINE_CAPSRC(num), \
1760 { } /* end */ \
1761}
1762
1763#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001764static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001765 _DEFINE_CAPMIX(num), \
1766 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001767}
1768
1769/* up to three ADCs */
1770DEFINE_CAPMIX(1);
1771DEFINE_CAPMIX(2);
1772DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001773DEFINE_CAPMIX_NOSRC(1);
1774DEFINE_CAPMIX_NOSRC(2);
1775DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001776
1777/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001778 * virtual master controls
1779 */
1780
1781/*
1782 * slave controls for virtual master
1783 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001784static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001785 "Front Playback Volume",
1786 "Surround Playback Volume",
1787 "Center Playback Volume",
1788 "LFE Playback Volume",
1789 "Side Playback Volume",
1790 "Headphone Playback Volume",
1791 "Speaker Playback Volume",
1792 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001793 "Line-Out Playback Volume",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001794 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001795 NULL,
1796};
1797
Takashi Iwaiea734962011-01-17 11:29:34 +01001798static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001799 "Front Playback Switch",
1800 "Surround Playback Switch",
1801 "Center Playback Switch",
1802 "LFE Playback Switch",
1803 "Side Playback Switch",
1804 "Headphone Playback Switch",
1805 "Speaker Playback Switch",
1806 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001807 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001808 "Line-Out Playback Switch",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001809 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001810 NULL,
1811};
1812
1813/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001814 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001816
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001817#define NID_MAPPING (-1)
1818
1819#define SUBDEV_SPEAKER_ (0 << 6)
1820#define SUBDEV_HP_ (1 << 6)
1821#define SUBDEV_LINE_ (2 << 6)
1822#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1823#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1824#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1825
Takashi Iwai603c4012008-07-30 15:01:44 +02001826static void alc_free_kctls(struct hda_codec *codec);
1827
Takashi Iwai67d634c2009-11-16 15:35:59 +01001828#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001829/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001830static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001831 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001832 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001833 { } /* end */
1834};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001835#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001836
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837static int alc_build_controls(struct hda_codec *codec)
1838{
1839 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001840 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001841 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001842 int i, j, err;
1843 unsigned int u;
1844 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
1846 for (i = 0; i < spec->num_mixers; i++) {
1847 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1848 if (err < 0)
1849 return err;
1850 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001851 if (spec->cap_mixer) {
1852 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1853 if (err < 0)
1854 return err;
1855 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001857 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001858 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001859 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 if (err < 0)
1861 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001862 if (!spec->no_analog) {
1863 err = snd_hda_create_spdif_share_sw(codec,
1864 &spec->multiout);
1865 if (err < 0)
1866 return err;
1867 spec->multiout.share_spdif = 1;
1868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 }
1870 if (spec->dig_in_nid) {
1871 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1872 if (err < 0)
1873 return err;
1874 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001875
Takashi Iwai67d634c2009-11-16 15:35:59 +01001876#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001877 /* create beep controls if needed */
1878 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001879 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001880 for (knew = alc_beep_mixer; knew->name; knew++) {
1881 struct snd_kcontrol *kctl;
1882 kctl = snd_ctl_new1(knew, codec);
1883 if (!kctl)
1884 return -ENOMEM;
1885 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001886 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001887 if (err < 0)
1888 return err;
1889 }
1890 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001891#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001892
Takashi Iwai2134ea42008-01-10 16:53:55 +01001893 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001894 if (!spec->no_analog &&
1895 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001896 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001897 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001898 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001899 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001900 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001901 if (err < 0)
1902 return err;
1903 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001904 if (!spec->no_analog &&
1905 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001906 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1907 NULL, alc_slave_sws);
1908 if (err < 0)
1909 return err;
1910 }
1911
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001912 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001913 if (spec->capsrc_nids || spec->adc_nids) {
1914 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1915 if (!kctl)
1916 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1917 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001918 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001919 if (!nids)
1920 nids = spec->adc_nids;
1921 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1922 if (err < 0)
1923 return err;
1924 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001925 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001926 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001927 const char *kname = kctl ? kctl->id.name : NULL;
1928 for (knew = spec->cap_mixer; knew->name; knew++) {
1929 if (kname && strcmp(knew->name, kname) == 0)
1930 continue;
1931 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1932 for (i = 0; kctl && i < kctl->count; i++) {
1933 err = snd_hda_add_nid(codec, kctl, i,
1934 spec->adc_nids[i]);
1935 if (err < 0)
1936 return err;
1937 }
1938 }
1939 }
1940
1941 /* other nid->control mapping */
1942 for (i = 0; i < spec->num_mixers; i++) {
1943 for (knew = spec->mixers[i]; knew->name; knew++) {
1944 if (knew->iface != NID_MAPPING)
1945 continue;
1946 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1947 if (kctl == NULL)
1948 continue;
1949 u = knew->subdevice;
1950 for (j = 0; j < 4; j++, u >>= 8) {
1951 nid = u & 0x3f;
1952 if (nid == 0)
1953 continue;
1954 switch (u & 0xc0) {
1955 case SUBDEV_SPEAKER_:
1956 nid = spec->autocfg.speaker_pins[nid];
1957 break;
1958 case SUBDEV_LINE_:
1959 nid = spec->autocfg.line_out_pins[nid];
1960 break;
1961 case SUBDEV_HP_:
1962 nid = spec->autocfg.hp_pins[nid];
1963 break;
1964 default:
1965 continue;
1966 }
1967 err = snd_hda_add_nid(codec, kctl, 0, nid);
1968 if (err < 0)
1969 return err;
1970 }
1971 u = knew->private_value;
1972 for (j = 0; j < 4; j++, u >>= 8) {
1973 nid = u & 0xff;
1974 if (nid == 0)
1975 continue;
1976 err = snd_hda_add_nid(codec, kctl, 0, nid);
1977 if (err < 0)
1978 return err;
1979 }
1980 }
1981 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001982
1983 alc_free_kctls(codec); /* no longer needed */
1984
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 return 0;
1986}
1987
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001988
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001990 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001991 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001992
Takashi Iwai584c0c42011-03-10 12:51:11 +01001993static void alc_init_special_input_src(struct hda_codec *codec);
1994
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995static int alc_init(struct hda_codec *codec)
1996{
1997 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001998 unsigned int i;
1999
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002000 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02002001 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002002
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002003 for (i = 0; i < spec->num_init_verbs; i++)
2004 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01002005 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002006
2007 if (spec->init_hook)
2008 spec->init_hook(codec);
2009
Takashi Iwai58701122011-01-13 15:41:45 +01002010 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2011
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002012 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 return 0;
2014}
2015
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002016static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2017{
2018 struct alc_spec *spec = codec->spec;
2019
2020 if (spec->unsol_event)
2021 spec->unsol_event(codec, res);
2022}
2023
Takashi Iwaicb53c622007-08-10 17:21:45 +02002024#ifdef CONFIG_SND_HDA_POWER_SAVE
2025static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2026{
2027 struct alc_spec *spec = codec->spec;
2028 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2029}
2030#endif
2031
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032/*
2033 * Analog playback callbacks
2034 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002035static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002037 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038{
2039 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002040 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2041 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042}
2043
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002044static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 struct hda_codec *codec,
2046 unsigned int stream_tag,
2047 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002048 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049{
2050 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002051 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2052 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053}
2054
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002055static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002057 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058{
2059 struct alc_spec *spec = codec->spec;
2060 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2061}
2062
2063/*
2064 * Digital out
2065 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002066static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002068 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069{
2070 struct alc_spec *spec = codec->spec;
2071 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2072}
2073
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002074static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002075 struct hda_codec *codec,
2076 unsigned int stream_tag,
2077 unsigned int format,
2078 struct snd_pcm_substream *substream)
2079{
2080 struct alc_spec *spec = codec->spec;
2081 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2082 stream_tag, format, substream);
2083}
2084
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002085static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002086 struct hda_codec *codec,
2087 struct snd_pcm_substream *substream)
2088{
2089 struct alc_spec *spec = codec->spec;
2090 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2091}
2092
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002093static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002095 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096{
2097 struct alc_spec *spec = codec->spec;
2098 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2099}
2100
2101/*
2102 * Analog capture
2103 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002104static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 struct hda_codec *codec,
2106 unsigned int stream_tag,
2107 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002108 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109{
2110 struct alc_spec *spec = codec->spec;
2111
Takashi Iwai63300792008-01-24 15:31:36 +01002112 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 stream_tag, 0, format);
2114 return 0;
2115}
2116
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002117static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002119 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120{
2121 struct alc_spec *spec = codec->spec;
2122
Takashi Iwai888afa12008-03-18 09:57:50 +01002123 snd_hda_codec_cleanup_stream(codec,
2124 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 return 0;
2126}
2127
Takashi Iwai840b64c2010-07-13 22:49:01 +02002128/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002129static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002130 struct hda_codec *codec,
2131 unsigned int stream_tag,
2132 unsigned int format,
2133 struct snd_pcm_substream *substream)
2134{
2135 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002136 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002137 spec->cur_adc_stream_tag = stream_tag;
2138 spec->cur_adc_format = format;
2139 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2140 return 0;
2141}
2142
Takashi Iwai21268962011-07-07 15:01:13 +02002143static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002144 struct hda_codec *codec,
2145 struct snd_pcm_substream *substream)
2146{
2147 struct alc_spec *spec = codec->spec;
2148 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2149 spec->cur_adc = 0;
2150 return 0;
2151}
2152
Takashi Iwai21268962011-07-07 15:01:13 +02002153static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002154 .substreams = 1,
2155 .channels_min = 2,
2156 .channels_max = 2,
2157 .nid = 0, /* fill later */
2158 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002159 .prepare = dyn_adc_capture_pcm_prepare,
2160 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002161 },
2162};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
2164/*
2165 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002166static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 .substreams = 1,
2168 .channels_min = 2,
2169 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002170 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002172 .open = alc_playback_pcm_open,
2173 .prepare = alc_playback_pcm_prepare,
2174 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 },
2176};
2177
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002178static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002179 .substreams = 1,
2180 .channels_min = 2,
2181 .channels_max = 2,
2182 /* NID is set in alc_build_pcms */
2183};
2184
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002185static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002186 .substreams = 1,
2187 .channels_min = 2,
2188 .channels_max = 2,
2189 /* NID is set in alc_build_pcms */
2190};
2191
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002192static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002193 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 .channels_min = 2,
2195 .channels_max = 2,
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 .prepare = alc_alt_capture_pcm_prepare,
2199 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 },
2201};
2202
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002203static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 .substreams = 1,
2205 .channels_min = 2,
2206 .channels_max = 2,
2207 /* NID is set in alc_build_pcms */
2208 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002209 .open = alc_dig_playback_pcm_open,
2210 .close = alc_dig_playback_pcm_close,
2211 .prepare = alc_dig_playback_pcm_prepare,
2212 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 },
2214};
2215
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002216static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 .substreams = 1,
2218 .channels_min = 2,
2219 .channels_max = 2,
2220 /* NID is set in alc_build_pcms */
2221};
2222
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002223/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002224static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002225 .substreams = 0,
2226 .channels_min = 0,
2227 .channels_max = 0,
2228};
2229
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230static int alc_build_pcms(struct hda_codec *codec)
2231{
2232 struct alc_spec *spec = codec->spec;
2233 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002234 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 int i;
2236
2237 codec->num_pcms = 1;
2238 codec->pcm_info = info;
2239
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002240 if (spec->no_analog)
2241 goto skip_analog;
2242
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002243 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2244 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002246
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002247 if (spec->multiout.dac_nids > 0) {
2248 p = spec->stream_analog_playback;
2249 if (!p)
2250 p = &alc_pcm_analog_playback;
2251 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002252 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2253 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002254 if (spec->adc_nids) {
2255 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002256 if (!p) {
2257 if (spec->dyn_adc_switch)
2258 p = &dyn_adc_pcm_analog_capture;
2259 else
2260 p = &alc_pcm_analog_capture;
2261 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002262 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002263 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
Takashi Iwai4a471b72005-12-07 13:56:29 +01002266 if (spec->channel_mode) {
2267 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2268 for (i = 0; i < spec->num_channel_mode; i++) {
2269 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2270 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 }
2273 }
2274
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002275 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002276 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002278 snprintf(spec->stream_name_digital,
2279 sizeof(spec->stream_name_digital),
2280 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002281 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002282 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002283 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002285 if (spec->dig_out_type)
2286 info->pcm_type = spec->dig_out_type;
2287 else
2288 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002289 if (spec->multiout.dig_out_nid) {
2290 p = spec->stream_digital_playback;
2291 if (!p)
2292 p = &alc_pcm_digital_playback;
2293 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2295 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002296 if (spec->dig_in_nid) {
2297 p = spec->stream_digital_capture;
2298 if (!p)
2299 p = &alc_pcm_digital_capture;
2300 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2302 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002303 /* FIXME: do we need this for all Realtek codec models? */
2304 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 }
2306
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002307 if (spec->no_analog)
2308 return 0;
2309
Takashi Iwaie08a0072006-09-07 17:52:14 +02002310 /* If the use of more than one ADC is requested for the current
2311 * model, configure a second analog capture-only PCM.
2312 */
2313 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002314 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002315 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002316 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002317 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002318 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002319 p = spec->stream_analog_alt_playback;
2320 if (!p)
2321 p = &alc_pcm_analog_alt_playback;
2322 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002323 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2324 spec->alt_dac_nid;
2325 } else {
2326 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2327 alc_pcm_null_stream;
2328 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2329 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002330 if (spec->num_adc_nids > 1) {
2331 p = spec->stream_analog_alt_capture;
2332 if (!p)
2333 p = &alc_pcm_analog_alt_capture;
2334 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002335 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2336 spec->adc_nids[1];
2337 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2338 spec->num_adc_nids - 1;
2339 } else {
2340 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2341 alc_pcm_null_stream;
2342 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002343 }
2344 }
2345
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 return 0;
2347}
2348
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002349static inline void alc_shutup(struct hda_codec *codec)
2350{
Takashi Iwai1c7161532011-04-07 10:37:16 +02002351 struct alc_spec *spec = codec->spec;
2352
2353 if (spec && spec->shutup)
2354 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002355 snd_hda_shutup_pins(codec);
2356}
2357
Takashi Iwai603c4012008-07-30 15:01:44 +02002358static void alc_free_kctls(struct hda_codec *codec)
2359{
2360 struct alc_spec *spec = codec->spec;
2361
2362 if (spec->kctls.list) {
2363 struct snd_kcontrol_new *kctl = spec->kctls.list;
2364 int i;
2365 for (i = 0; i < spec->kctls.used; i++)
2366 kfree(kctl[i].name);
2367 }
2368 snd_array_free(&spec->kctls);
2369}
2370
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371static void alc_free(struct hda_codec *codec)
2372{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002373 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002374
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002375 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002376 return;
2377
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002378 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002379 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002380 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002381 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002382 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383}
2384
Hector Martinf5de24b2009-12-20 22:51:31 +01002385#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002386static void alc_power_eapd(struct hda_codec *codec)
2387{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002388 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002389}
2390
Hector Martinf5de24b2009-12-20 22:51:31 +01002391static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2392{
2393 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002394 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002395 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002396 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002397 return 0;
2398}
2399#endif
2400
Takashi Iwai2a439522011-07-26 09:52:50 +02002401#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002402static int alc_resume(struct hda_codec *codec)
2403{
Takashi Iwai1c7161532011-04-07 10:37:16 +02002404 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002405 codec->patch_ops.init(codec);
2406 snd_hda_codec_resume_amp(codec);
2407 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002408 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002409 return 0;
2410}
Takashi Iwaie044c392008-10-27 16:56:24 +01002411#endif
2412
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413/*
2414 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002415static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 .build_controls = alc_build_controls,
2417 .build_pcms = alc_build_pcms,
2418 .init = alc_init,
2419 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002420 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002421#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002422 .resume = alc_resume,
2423#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002424#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002425 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002426 .check_power_status = alc_check_power_status,
2427#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002428 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429};
2430
Kailang Yangc027ddc2010-03-19 11:33:06 +01002431/* replace the codec chip_name with the given string */
2432static int alc_codec_rename(struct hda_codec *codec, const char *name)
2433{
2434 kfree(codec->chip_name);
2435 codec->chip_name = kstrdup(name, GFP_KERNEL);
2436 if (!codec->chip_name) {
2437 alc_free(codec);
2438 return -ENOMEM;
2439 }
2440 return 0;
2441}
2442
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002443/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002444 * Automatic parse of I/O pins from the BIOS configuration
2445 */
2446
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002447enum {
2448 ALC_CTL_WIDGET_VOL,
2449 ALC_CTL_WIDGET_MUTE,
2450 ALC_CTL_BIND_MUTE,
2451};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002452static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002453 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2454 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002455 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002456};
2457
2458/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002459static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002460 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002461{
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002462 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002463
Takashi Iwaice764ab2011-04-27 16:35:23 +02002464 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002465 if (!knew)
2466 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002467 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002468 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002469 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002470 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002471 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002472 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002473 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002474 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002475 return 0;
2476}
2477
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002478static int add_control_with_pfx(struct alc_spec *spec, int type,
2479 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002480 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002481{
2482 char name[32];
2483 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002484 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002485}
2486
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002487#define add_pb_vol_ctrl(spec, type, pfx, val) \
2488 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2489#define add_pb_sw_ctrl(spec, type, pfx, val) \
2490 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2491#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2492 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2493#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2494 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002495
Takashi Iwai6843ca12011-06-24 11:03:58 +02002496static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2497 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002498{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002499 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002500 static const char * const chname[4] = {
2501 "Front", "Surround", NULL /*CLFE*/, "Side"
2502 };
Takashi Iwaice764ab2011-04-27 16:35:23 +02002503
Takashi Iwai6843ca12011-06-24 11:03:58 +02002504 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002505 if (cfg->line_outs == 1 && !spec->multi_ios &&
2506 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002507 return "Master";
2508
2509 switch (cfg->line_out_type) {
2510 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002511 if (cfg->line_outs == 1)
2512 return "Speaker";
2513 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002514 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002515 /* for multi-io case, only the primary out */
2516 if (ch && spec->multi_ios)
2517 break;
2518 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002519 return "Headphone";
2520 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002521 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002522 return "PCM";
2523 break;
2524 }
Takashi Iwai6843ca12011-06-24 11:03:58 +02002525 return chname[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002526}
2527
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002528/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002529static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002530 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002531 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002532{
Kailang Yangdf694da2005-12-05 19:42:22 +01002533 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002534
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002535 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002536 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2537 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002538 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002539 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002540 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2541 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002542 return err;
2543 return 0;
2544}
2545
Takashi Iwai05f5f472009-08-25 13:10:18 +02002546static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002547{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002548 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2549 return (pincap & AC_PINCAP_IN) != 0;
2550}
2551
Takashi Iwai1d045db2011-07-07 18:23:21 +02002552/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002553static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002554{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002555 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002556 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002557 hda_nid_t *adc_nids = spec->private_adc_nids;
2558 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2559 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2560 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002561 int i, nums = 0;
2562
2563 nid = codec->start_nid;
2564 for (i = 0; i < codec->num_nodes; i++, nid++) {
2565 hda_nid_t src;
2566 const hda_nid_t *list;
2567 unsigned int caps = get_wcaps(codec, nid);
2568 int type = get_wcaps_type(caps);
2569
2570 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2571 continue;
2572 adc_nids[nums] = nid;
2573 cap_nids[nums] = nid;
2574 src = nid;
2575 for (;;) {
2576 int n;
2577 type = get_wcaps_type(get_wcaps(codec, src));
2578 if (type == AC_WID_PIN)
2579 break;
2580 if (type == AC_WID_AUD_SEL) {
2581 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002582 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002583 break;
2584 }
2585 n = snd_hda_get_conn_list(codec, src, &list);
2586 if (n > 1) {
2587 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002588 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002589 break;
2590 } else if (n != 1)
2591 break;
2592 src = *list;
2593 }
2594 if (++nums >= max_nums)
2595 break;
2596 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002597 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002598 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002599 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002600 return nums;
2601}
2602
Takashi Iwai05f5f472009-08-25 13:10:18 +02002603/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002604static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002605{
2606 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002607 const struct auto_pin_cfg *cfg = &spec->autocfg;
2608 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002609 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002610 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002611 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002612 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002613
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002614 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002615 if (num_adcs < 0)
2616 return 0;
2617
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002618 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002619 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002620 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002621
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002622 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002623 if (!alc_is_input_pin(codec, pin))
2624 continue;
2625
David Henningsson5322bf22011-01-05 11:03:56 +01002626 label = hda_get_autocfg_input_label(codec, cfg, i);
2627 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002628 type_idx++;
2629 else
2630 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002631 prev_label = label;
2632
Takashi Iwai05f5f472009-08-25 13:10:18 +02002633 if (mixer) {
2634 idx = get_connection_index(codec, mixer, pin);
2635 if (idx >= 0) {
2636 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002637 label, type_idx,
2638 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002639 if (err < 0)
2640 return err;
2641 }
2642 }
2643
Takashi Iwaib7821702011-07-06 15:12:46 +02002644 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002645 hda_nid_t cap = spec->capsrc_nids ?
2646 spec->capsrc_nids[c] : spec->adc_nids[c];
2647 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002648 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002649 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002650 snd_hda_add_imux_item(imux, label, idx, NULL);
2651 break;
2652 }
2653 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002654 }
Takashi Iwai21268962011-07-07 15:01:13 +02002655
2656 spec->num_mux_defs = 1;
2657 spec->input_mux = imux;
2658
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002659 return 0;
2660}
2661
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002662static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2663 unsigned int pin_type)
2664{
2665 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2666 pin_type);
2667 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002668 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2669 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002670 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002671}
2672
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002673static int get_pin_type(int line_out_type)
2674{
2675 if (line_out_type == AUTO_PIN_HP_OUT)
2676 return PIN_HP;
2677 else
2678 return PIN_OUT;
2679}
2680
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002681static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002682{
2683 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002684 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002685 int i;
2686
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002687 for (i = 0; i < cfg->num_inputs; i++) {
2688 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002689 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002690 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002691 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002692 snd_hda_codec_write(codec, nid, 0,
2693 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002694 AMP_OUT_MUTE);
2695 }
2696 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002697
2698 /* mute all loopback inputs */
2699 if (spec->mixer_nid) {
2700 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2701 for (i = 0; i < nums; i++)
2702 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2703 AC_VERB_SET_AMP_GAIN_MUTE,
2704 AMP_IN_MUTE(i));
2705 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002706}
2707
Takashi Iwai7085ec12009-10-02 09:03:58 +02002708/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002709static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002710{
Takashi Iwai604401a2011-04-27 15:14:23 +02002711 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002712 int i, num;
2713
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002714 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2715 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002716 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2717 for (i = 0; i < num; i++) {
2718 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2719 return list[i];
2720 }
2721 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002722}
2723
Takashi Iwai604401a2011-04-27 15:14:23 +02002724/* go down to the selector widget before the mixer */
2725static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2726{
2727 hda_nid_t srcs[5];
2728 int num = snd_hda_get_connections(codec, pin, srcs,
2729 ARRAY_SIZE(srcs));
2730 if (num != 1 ||
2731 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2732 return pin;
2733 return srcs[0];
2734}
2735
Takashi Iwai7085ec12009-10-02 09:03:58 +02002736/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002737static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002738 hda_nid_t dac)
2739{
David Henningssoncc1c4522010-11-24 14:17:47 +01002740 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002741 int i, num;
2742
Takashi Iwai604401a2011-04-27 15:14:23 +02002743 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002744 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2745 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002746 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002747 return mix[i];
2748 }
2749 return 0;
2750}
2751
Takashi Iwaice764ab2011-04-27 16:35:23 +02002752/* select the connection from pin to DAC if needed */
2753static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2754 hda_nid_t dac)
2755{
2756 hda_nid_t mix[5];
2757 int i, num;
2758
2759 pin = alc_go_down_to_selector(codec, pin);
2760 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2761 if (num < 2)
2762 return 0;
2763 for (i = 0; i < num; i++) {
2764 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2765 snd_hda_codec_update_cache(codec, pin, 0,
2766 AC_VERB_SET_CONNECT_SEL, i);
2767 return 0;
2768 }
2769 }
2770 return 0;
2771}
2772
Takashi Iwai7085ec12009-10-02 09:03:58 +02002773/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002774static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002775{
2776 struct alc_spec *spec = codec->spec;
2777 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002778 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002779
Takashi Iwai604401a2011-04-27 15:14:23 +02002780 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002781 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002782 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002783 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002784 if (!nid)
2785 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002786 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2787 spec->multiout.num_dacs))
2788 continue;
2789 if (spec->multiout.hp_nid == nid)
2790 continue;
2791 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2792 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2793 continue;
2794 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002795 }
2796 return 0;
2797}
2798
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002799static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2800{
2801 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2802 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2803 return alc_auto_look_for_dac(codec, pin);
2804 return 0;
2805}
2806
Takashi Iwai7085ec12009-10-02 09:03:58 +02002807/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002808static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002809{
2810 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002811 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002812 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002813 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002814
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002815 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002816 /* set num_dacs once to full for alc_auto_look_for_dac() */
2817 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002818 spec->multiout.hp_nid = 0;
2819 spec->multiout.extra_out_nid[0] = 0;
2820 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2821 spec->multiout.dac_nids = spec->private_dac_nids;
2822
2823 /* fill hard-wired DACs first */
2824 if (!redone) {
2825 for (i = 0; i < cfg->line_outs; i++)
2826 spec->private_dac_nids[i] =
2827 get_dac_if_single(codec, cfg->line_out_pins[i]);
2828 if (cfg->hp_outs)
2829 spec->multiout.hp_nid =
2830 get_dac_if_single(codec, cfg->hp_pins[0]);
2831 if (cfg->speaker_outs)
2832 spec->multiout.extra_out_nid[0] =
2833 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002834 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002835
2836 for (i = 0; i < cfg->line_outs; i++) {
2837 hda_nid_t pin = cfg->line_out_pins[i];
2838 if (spec->private_dac_nids[i])
2839 continue;
2840 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2841 if (!spec->private_dac_nids[i] && !redone) {
2842 /* if we can't find primary DACs, re-probe without
2843 * checking the hard-wired DACs
2844 */
2845 redone = true;
2846 goto again;
2847 }
2848 }
2849
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002850 /* re-count num_dacs and squash invalid entries */
2851 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002852 for (i = 0; i < cfg->line_outs; i++) {
2853 if (spec->private_dac_nids[i])
2854 spec->multiout.num_dacs++;
2855 else
2856 memmove(spec->private_dac_nids + i,
2857 spec->private_dac_nids + i + 1,
2858 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2859 }
2860
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002861 if (cfg->hp_outs && !spec->multiout.hp_nid)
2862 spec->multiout.hp_nid =
2863 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2864 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2865 spec->multiout.extra_out_nid[0] =
2866 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2867
Takashi Iwai7085ec12009-10-02 09:03:58 +02002868 return 0;
2869}
2870
Takashi Iwai343a04b2011-07-06 14:28:39 +02002871static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002872 const char *pfx, int cidx,
2873 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002874{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002875 if (!nid)
2876 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002877 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2878 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002879}
2880
Takashi Iwai343a04b2011-07-06 14:28:39 +02002881#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2882 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002883
2884/* create a mute-switch for the given mixer widget;
2885 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2886 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002887static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002888 const char *pfx, int cidx,
2889 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002890{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002891 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002892 int type;
2893 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002894 if (!nid)
2895 return 0;
2896 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2897 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2898 type = ALC_CTL_WIDGET_MUTE;
2899 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2900 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002901 type = ALC_CTL_WIDGET_MUTE;
2902 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2903 } else {
2904 type = ALC_CTL_BIND_MUTE;
2905 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2906 }
2907 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002908}
2909
Takashi Iwai343a04b2011-07-06 14:28:39 +02002910#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2911 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002912
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002913static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2914 hda_nid_t pin, hda_nid_t dac)
2915{
2916 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2917 if (nid_has_mute(codec, pin, HDA_OUTPUT))
2918 return pin;
2919 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
2920 return mix;
2921 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
2922 return dac;
2923 return 0;
2924}
2925
2926static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
2927 hda_nid_t pin, hda_nid_t dac)
2928{
2929 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2930 if (nid_has_volume(codec, dac, HDA_OUTPUT))
2931 return dac;
2932 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
2933 return mix;
2934 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
2935 return pin;
2936 return 0;
2937}
2938
Takashi Iwai7085ec12009-10-02 09:03:58 +02002939/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002940static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002941 const struct auto_pin_cfg *cfg)
2942{
2943 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002944 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002945
Takashi Iwaice764ab2011-04-27 16:35:23 +02002946 noutputs = cfg->line_outs;
2947 if (spec->multi_ios > 0)
2948 noutputs += spec->multi_ios;
2949
2950 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002951 const char *name;
2952 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002953 hda_nid_t dac, pin;
2954 hda_nid_t sw, vol;
2955
2956 dac = spec->multiout.dac_nids[i];
2957 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002958 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002959 if (i >= cfg->line_outs)
2960 pin = spec->multi_io[i - 1].pin;
2961 else
2962 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002963
2964 sw = alc_look_for_out_mute_nid(codec, pin, dac);
2965 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02002966 name = alc_get_line_out_pfx(spec, i, true, &index);
2967 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002968 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002969 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002970 if (err < 0)
2971 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002972 err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002973 if (err < 0)
2974 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002975 err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002976 if (err < 0)
2977 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002978 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002979 if (err < 0)
2980 return err;
2981 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002982 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002983 if (err < 0)
2984 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002985 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002986 if (err < 0)
2987 return err;
2988 }
2989 }
2990 return 0;
2991}
2992
2993/* add playback controls for speaker and HP outputs */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002994static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002995 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002996{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002997 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002998 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002999 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003000
3001 if (!pin)
3002 return 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003003 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02003004 /* the corresponding DAC is already occupied */
3005 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
3006 return 0; /* no way */
3007 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02003008 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003009 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3010 }
3011
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003012 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3013 vol = alc_look_for_out_vol_nid(codec, pin, dac);
3014 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003015 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003016 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003017 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003018 if (err < 0)
3019 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003020 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003021}
3022
Takashi Iwai343a04b2011-07-06 14:28:39 +02003023static int alc_auto_create_hp_out(struct hda_codec *codec)
3024{
3025 struct alc_spec *spec = codec->spec;
3026 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3027 spec->multiout.hp_nid,
3028 "Headphone");
3029}
3030
3031static int alc_auto_create_speaker_out(struct hda_codec *codec)
3032{
3033 struct alc_spec *spec = codec->spec;
3034 return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
3035 spec->multiout.extra_out_nid[0],
3036 "Speaker");
3037}
3038
Takashi Iwai343a04b2011-07-06 14:28:39 +02003039static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003040 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003041 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003042{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003043 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003044 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003045 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003046
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003047 alc_set_pin_output(codec, pin, pin_type);
3048 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003049 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003050 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003051 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003052 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003053 mix = srcs[i];
3054 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003055 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003056 if (!mix)
3057 return;
3058
3059 /* need the manual connection? */
3060 if (num > 1)
3061 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3062 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003063 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3064 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003065 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003066 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003067 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003068 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003069 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003070 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3071 if (nid)
3072 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3073 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003074}
3075
Takashi Iwai343a04b2011-07-06 14:28:39 +02003076static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003077{
3078 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003079 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003080 int i;
3081
3082 for (i = 0; i <= HDA_SIDE; i++) {
3083 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3084 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003085 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003086 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003087 }
3088}
3089
Takashi Iwai343a04b2011-07-06 14:28:39 +02003090static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003091{
3092 struct alc_spec *spec = codec->spec;
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003093 hda_nid_t pin, dac;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003094
3095 pin = spec->autocfg.hp_pins[0];
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003096 if (pin) {
3097 dac = spec->multiout.hp_nid;
3098 if (!dac)
3099 dac = spec->multiout.dac_nids[0];
3100 alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
3101 }
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003102 pin = spec->autocfg.speaker_pins[0];
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003103 if (pin) {
3104 dac = spec->multiout.extra_out_nid[0];
3105 if (!dac)
3106 dac = spec->multiout.dac_nids[0];
3107 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
3108 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003109}
3110
Takashi Iwaice764ab2011-04-27 16:35:23 +02003111/*
3112 * multi-io helper
3113 */
3114static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3115 unsigned int location)
3116{
3117 struct alc_spec *spec = codec->spec;
3118 struct auto_pin_cfg *cfg = &spec->autocfg;
3119 int type, i, num_pins = 0;
3120
3121 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3122 for (i = 0; i < cfg->num_inputs; i++) {
3123 hda_nid_t nid = cfg->inputs[i].pin;
3124 hda_nid_t dac;
3125 unsigned int defcfg, caps;
3126 if (cfg->inputs[i].type != type)
3127 continue;
3128 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3129 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3130 continue;
3131 if (location && get_defcfg_location(defcfg) != location)
3132 continue;
3133 caps = snd_hda_query_pin_caps(codec, nid);
3134 if (!(caps & AC_PINCAP_OUT))
3135 continue;
3136 dac = alc_auto_look_for_dac(codec, nid);
3137 if (!dac)
3138 continue;
3139 spec->multi_io[num_pins].pin = nid;
3140 spec->multi_io[num_pins].dac = dac;
3141 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003142 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003143 }
3144 }
3145 spec->multiout.num_dacs = 1;
3146 if (num_pins < 2)
3147 return 0;
3148 return num_pins;
3149}
3150
3151static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3152 struct snd_ctl_elem_info *uinfo)
3153{
3154 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3155 struct alc_spec *spec = codec->spec;
3156
3157 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3158 uinfo->count = 1;
3159 uinfo->value.enumerated.items = spec->multi_ios + 1;
3160 if (uinfo->value.enumerated.item > spec->multi_ios)
3161 uinfo->value.enumerated.item = spec->multi_ios;
3162 sprintf(uinfo->value.enumerated.name, "%dch",
3163 (uinfo->value.enumerated.item + 1) * 2);
3164 return 0;
3165}
3166
3167static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3168 struct snd_ctl_elem_value *ucontrol)
3169{
3170 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3171 struct alc_spec *spec = codec->spec;
3172 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3173 return 0;
3174}
3175
3176static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3177{
3178 struct alc_spec *spec = codec->spec;
3179 hda_nid_t nid = spec->multi_io[idx].pin;
3180
3181 if (!spec->multi_io[idx].ctl_in)
3182 spec->multi_io[idx].ctl_in =
3183 snd_hda_codec_read(codec, nid, 0,
3184 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3185 if (output) {
3186 snd_hda_codec_update_cache(codec, nid, 0,
3187 AC_VERB_SET_PIN_WIDGET_CONTROL,
3188 PIN_OUT);
3189 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3190 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3191 HDA_AMP_MUTE, 0);
3192 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3193 } else {
3194 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3195 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3196 HDA_AMP_MUTE, HDA_AMP_MUTE);
3197 snd_hda_codec_update_cache(codec, nid, 0,
3198 AC_VERB_SET_PIN_WIDGET_CONTROL,
3199 spec->multi_io[idx].ctl_in);
3200 }
3201 return 0;
3202}
3203
3204static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3205 struct snd_ctl_elem_value *ucontrol)
3206{
3207 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3208 struct alc_spec *spec = codec->spec;
3209 int i, ch;
3210
3211 ch = ucontrol->value.enumerated.item[0];
3212 if (ch < 0 || ch > spec->multi_ios)
3213 return -EINVAL;
3214 if (ch == (spec->ext_channel_count - 1) / 2)
3215 return 0;
3216 spec->ext_channel_count = (ch + 1) * 2;
3217 for (i = 0; i < spec->multi_ios; i++)
3218 alc_set_multi_io(codec, i, i < ch);
3219 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003220 if (spec->need_dac_fix && !spec->const_channel_count)
3221 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003222 return 1;
3223}
3224
Takashi Iwaia9111322011-05-02 11:30:18 +02003225static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003226 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3227 .name = "Channel Mode",
3228 .info = alc_auto_ch_mode_info,
3229 .get = alc_auto_ch_mode_get,
3230 .put = alc_auto_ch_mode_put,
3231};
3232
Takashi Iwaicb053a82011-06-27 11:32:07 +02003233static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
3234 int (*fill_dac)(struct hda_codec *))
Takashi Iwaice764ab2011-04-27 16:35:23 +02003235{
3236 struct alc_spec *spec = codec->spec;
3237 struct auto_pin_cfg *cfg = &spec->autocfg;
3238 unsigned int location, defcfg;
3239 int num_pins;
3240
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003241 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3242 /* use HP as primary out */
3243 cfg->speaker_outs = cfg->line_outs;
3244 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3245 sizeof(cfg->speaker_pins));
3246 cfg->line_outs = cfg->hp_outs;
3247 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3248 cfg->hp_outs = 0;
3249 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3250 cfg->line_out_type = AUTO_PIN_HP_OUT;
Takashi Iwaicb053a82011-06-27 11:32:07 +02003251 if (fill_dac)
3252 fill_dac(codec);
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003253 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003254 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003255 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003256 return 0;
3257
3258 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3259 location = get_defcfg_location(defcfg);
3260
3261 num_pins = alc_auto_fill_multi_ios(codec, location);
3262 if (num_pins > 0) {
3263 struct snd_kcontrol_new *knew;
3264
3265 knew = alc_kcontrol_new(spec);
3266 if (!knew)
3267 return -ENOMEM;
3268 *knew = alc_auto_channel_mode_enum;
3269 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3270 if (!knew->name)
3271 return -ENOMEM;
3272
3273 spec->multi_ios = num_pins;
3274 spec->ext_channel_count = 2;
3275 spec->multiout.num_dacs = num_pins + 1;
3276 }
3277 return 0;
3278}
3279
Takashi Iwai1d045db2011-07-07 18:23:21 +02003280/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3281 * active input pins
3282 */
3283static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3284{
3285 struct alc_spec *spec = codec->spec;
3286 const struct hda_input_mux *imux;
3287 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3288 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3289 int i, n, nums;
3290
3291 imux = spec->input_mux;
3292 if (!imux)
3293 return;
3294 if (spec->dyn_adc_switch)
3295 return;
3296
3297 nums = 0;
3298 for (n = 0; n < spec->num_adc_nids; n++) {
3299 hda_nid_t cap = spec->private_capsrc_nids[n];
3300 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3301 for (i = 0; i < imux->num_items; i++) {
3302 hda_nid_t pin = spec->imux_pins[i];
3303 if (pin) {
3304 if (get_connection_index(codec, cap, pin) < 0)
3305 break;
3306 } else if (num_conns <= imux->items[i].index)
3307 break;
3308 }
3309 if (i >= imux->num_items) {
3310 adc_nids[nums] = spec->private_adc_nids[n];
3311 capsrc_nids[nums++] = cap;
3312 }
3313 }
3314 if (!nums) {
3315 /* check whether ADC-switch is possible */
3316 if (!alc_check_dyn_adc_switch(codec)) {
3317 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3318 " using fallback 0x%x\n",
3319 codec->chip_name, spec->private_adc_nids[0]);
3320 spec->num_adc_nids = 1;
3321 spec->auto_mic = 0;
3322 return;
3323 }
3324 } else if (nums != spec->num_adc_nids) {
3325 memcpy(spec->private_adc_nids, adc_nids,
3326 nums * sizeof(hda_nid_t));
3327 memcpy(spec->private_capsrc_nids, capsrc_nids,
3328 nums * sizeof(hda_nid_t));
3329 spec->num_adc_nids = nums;
3330 }
3331
3332 if (spec->auto_mic)
3333 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3334 else if (spec->input_mux->num_items == 1)
3335 spec->num_adc_nids = 1; /* reduce to a single ADC */
3336}
3337
3338/*
3339 * initialize ADC paths
3340 */
3341static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3342{
3343 struct alc_spec *spec = codec->spec;
3344 hda_nid_t nid;
3345
3346 nid = spec->adc_nids[adc_idx];
3347 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003348 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003349 snd_hda_codec_write(codec, nid, 0,
3350 AC_VERB_SET_AMP_GAIN_MUTE,
3351 AMP_IN_MUTE(0));
3352 return;
3353 }
3354 if (!spec->capsrc_nids)
3355 return;
3356 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003357 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003358 snd_hda_codec_write(codec, nid, 0,
3359 AC_VERB_SET_AMP_GAIN_MUTE,
3360 AMP_OUT_MUTE);
3361}
3362
3363static void alc_auto_init_input_src(struct hda_codec *codec)
3364{
3365 struct alc_spec *spec = codec->spec;
3366 int c, nums;
3367
3368 for (c = 0; c < spec->num_adc_nids; c++)
3369 alc_auto_init_adc(codec, c);
3370 if (spec->dyn_adc_switch)
3371 nums = 1;
3372 else
3373 nums = spec->num_adc_nids;
3374 for (c = 0; c < nums; c++)
3375 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3376}
3377
3378/* add mic boosts if needed */
3379static int alc_auto_add_mic_boost(struct hda_codec *codec)
3380{
3381 struct alc_spec *spec = codec->spec;
3382 struct auto_pin_cfg *cfg = &spec->autocfg;
3383 int i, err;
3384 int type_idx = 0;
3385 hda_nid_t nid;
3386 const char *prev_label = NULL;
3387
3388 for (i = 0; i < cfg->num_inputs; i++) {
3389 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3390 break;
3391 nid = cfg->inputs[i].pin;
3392 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3393 const char *label;
3394 char boost_label[32];
3395
3396 label = hda_get_autocfg_input_label(codec, cfg, i);
3397 if (prev_label && !strcmp(label, prev_label))
3398 type_idx++;
3399 else
3400 type_idx = 0;
3401 prev_label = label;
3402
3403 snprintf(boost_label, sizeof(boost_label),
3404 "%s Boost Volume", label);
3405 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3406 boost_label, type_idx,
3407 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3408 if (err < 0)
3409 return err;
3410 }
3411 }
3412 return 0;
3413}
3414
3415/* select or unmute the given capsrc route */
3416static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3417 int idx)
3418{
3419 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3420 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3421 HDA_AMP_MUTE, 0);
3422 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3423 snd_hda_codec_write_cache(codec, cap, 0,
3424 AC_VERB_SET_CONNECT_SEL, idx);
3425 }
3426}
3427
3428/* set the default connection to that pin */
3429static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3430{
3431 struct alc_spec *spec = codec->spec;
3432 int i;
3433
3434 if (!pin)
3435 return 0;
3436 for (i = 0; i < spec->num_adc_nids; i++) {
3437 hda_nid_t cap = spec->capsrc_nids ?
3438 spec->capsrc_nids[i] : spec->adc_nids[i];
3439 int idx;
3440
3441 idx = get_connection_index(codec, cap, pin);
3442 if (idx < 0)
3443 continue;
3444 select_or_unmute_capsrc(codec, cap, idx);
3445 return i; /* return the found index */
3446 }
3447 return -1; /* not found */
3448}
3449
3450/* initialize some special cases for input sources */
3451static void alc_init_special_input_src(struct hda_codec *codec)
3452{
3453 struct alc_spec *spec = codec->spec;
3454 int i;
3455
3456 for (i = 0; i < spec->autocfg.num_inputs; i++)
3457 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3458}
3459
3460/* assign appropriate capture mixers */
3461static void set_capture_mixer(struct hda_codec *codec)
3462{
3463 struct alc_spec *spec = codec->spec;
3464 static const struct snd_kcontrol_new *caps[2][3] = {
3465 { alc_capture_mixer_nosrc1,
3466 alc_capture_mixer_nosrc2,
3467 alc_capture_mixer_nosrc3 },
3468 { alc_capture_mixer1,
3469 alc_capture_mixer2,
3470 alc_capture_mixer3 },
3471 };
3472
3473 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003474 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003475 if (!spec->capsrc_nids)
3476 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003477 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003478 return; /* no volume in capsrc, too */
3479 spec->vol_in_capsrc = 1;
3480 }
3481
3482 if (spec->num_adc_nids > 0) {
3483 int mux = 0;
3484 int num_adcs = 0;
3485
3486 if (spec->input_mux && spec->input_mux->num_items > 1)
3487 mux = 1;
3488 if (spec->auto_mic) {
3489 num_adcs = 1;
3490 mux = 0;
3491 } else if (spec->dyn_adc_switch)
3492 num_adcs = 1;
3493 if (!num_adcs) {
3494 if (spec->num_adc_nids > 3)
3495 spec->num_adc_nids = 3;
3496 else if (!spec->num_adc_nids)
3497 return;
3498 num_adcs = spec->num_adc_nids;
3499 }
3500 spec->cap_mixer = caps[mux][num_adcs - 1];
3501 }
3502}
3503
3504/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003505 * standard auto-parser initializations
3506 */
3507static void alc_auto_init_std(struct hda_codec *codec)
3508{
3509 struct alc_spec *spec = codec->spec;
3510 alc_auto_init_multi_out(codec);
3511 alc_auto_init_extra_out(codec);
3512 alc_auto_init_analog_input(codec);
3513 alc_auto_init_input_src(codec);
3514 alc_auto_init_digital(codec);
3515 if (spec->unsol_event)
3516 alc_inithook(codec);
3517}
3518
3519/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003520 * Digital-beep handlers
3521 */
3522#ifdef CONFIG_SND_HDA_INPUT_BEEP
3523#define set_beep_amp(spec, nid, idx, dir) \
3524 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3525
3526static const struct snd_pci_quirk beep_white_list[] = {
3527 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3528 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3529 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3530 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3531 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3532 {}
3533};
3534
3535static inline int has_cdefine_beep(struct hda_codec *codec)
3536{
3537 struct alc_spec *spec = codec->spec;
3538 const struct snd_pci_quirk *q;
3539 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3540 if (q)
3541 return q->value;
3542 return spec->cdefine.enable_pcbeep;
3543}
3544#else
3545#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3546#define has_cdefine_beep(codec) 0
3547#endif
3548
3549/* parse the BIOS configuration and set up the alc_spec */
3550/* return 1 if successful, 0 if the proper config is not found,
3551 * or a negative error code
3552 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003553static int alc_parse_auto_config(struct hda_codec *codec,
3554 const hda_nid_t *ignore_nids,
3555 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003556{
3557 struct alc_spec *spec = codec->spec;
3558 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003559
3560 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003561 ignore_nids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003562 if (err < 0)
3563 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003564 if (!spec->autocfg.line_outs) {
3565 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
3566 spec->multiout.max_channels = 2;
3567 spec->no_analog = 1;
3568 goto dig_only;
3569 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003570 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003571 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003572 err = alc_auto_fill_dac_nids(codec);
3573 if (err < 0)
3574 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003575 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
3576 if (err < 0)
3577 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003578 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
3579 if (err < 0)
3580 return err;
3581 err = alc_auto_create_hp_out(codec);
3582 if (err < 0)
3583 return err;
3584 err = alc_auto_create_speaker_out(codec);
3585 if (err < 0)
3586 return err;
3587 err = alc_auto_create_input_ctls(codec);
3588 if (err < 0)
3589 return err;
3590
3591 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3592
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003593 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02003594 alc_auto_parse_digital(codec);
3595
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003596 if (!spec->no_analog)
3597 alc_remove_invalid_adc_nids(codec);
3598
3599 if (ssid_nids)
3600 alc_ssid_check(codec, ssid_nids);
3601
3602 if (!spec->no_analog) {
3603 alc_auto_check_switches(codec);
3604 err = alc_auto_add_mic_boost(codec);
3605 if (err < 0)
3606 return err;
3607 }
3608
Takashi Iwai1d045db2011-07-07 18:23:21 +02003609 if (spec->kctls.list)
3610 add_mixer(spec, spec->kctls.list);
3611
Takashi Iwai1d045db2011-07-07 18:23:21 +02003612 return 1;
3613}
3614
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003615static int alc880_parse_auto_config(struct hda_codec *codec)
3616{
3617 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3618 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3619 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
3620}
3621
Takashi Iwai1d045db2011-07-07 18:23:21 +02003622#ifdef CONFIG_SND_HDA_POWER_SAVE
3623static const struct hda_amp_list alc880_loopbacks[] = {
3624 { 0x0b, HDA_INPUT, 0 },
3625 { 0x0b, HDA_INPUT, 1 },
3626 { 0x0b, HDA_INPUT, 2 },
3627 { 0x0b, HDA_INPUT, 3 },
3628 { 0x0b, HDA_INPUT, 4 },
3629 { } /* end */
3630};
3631#endif
3632
3633/*
3634 * board setups
3635 */
3636#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3637#define alc_board_config \
3638 snd_hda_check_board_config
3639#define alc_board_codec_sid_config \
3640 snd_hda_check_board_codec_sid_config
3641#include "alc_quirks.c"
3642#else
3643#define alc_board_config(codec, nums, models, tbl) -1
3644#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3645#define setup_preset(codec, x) /* NOP */
3646#endif
3647
3648/*
3649 * OK, here we have finally the patch for ALC880
3650 */
3651#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3652#include "alc880_quirks.c"
3653#endif
3654
3655static int patch_alc880(struct hda_codec *codec)
3656{
3657 struct alc_spec *spec;
3658 int board_config;
3659 int err;
3660
3661 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3662 if (spec == NULL)
3663 return -ENOMEM;
3664
3665 codec->spec = spec;
3666
3667 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003668 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003669
3670 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3671 alc880_models, alc880_cfg_tbl);
3672 if (board_config < 0) {
3673 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3674 codec->chip_name);
3675 board_config = ALC_MODEL_AUTO;
3676 }
3677
3678 if (board_config == ALC_MODEL_AUTO) {
3679 /* automatic parse from the BIOS config */
3680 err = alc880_parse_auto_config(codec);
3681 if (err < 0) {
3682 alc_free(codec);
3683 return err;
3684 }
3685#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3686 else if (!err) {
3687 printk(KERN_INFO
3688 "hda_codec: Cannot set up configuration "
3689 "from BIOS. Using 3-stack mode...\n");
3690 board_config = ALC880_3ST;
3691 }
3692#endif
3693 }
3694
Takashi Iwai1d045db2011-07-07 18:23:21 +02003695 if (board_config != ALC_MODEL_AUTO)
3696 setup_preset(codec, &alc880_presets[board_config]);
3697
Takashi Iwai60a6a842011-07-27 14:01:24 +02003698 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003699 alc_auto_fill_adc_caps(codec);
3700 alc_rebuild_imux_for_auto_mic(codec);
3701 alc_remove_invalid_adc_nids(codec);
3702 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003703
3704 if (!spec->no_analog && !spec->cap_mixer)
3705 set_capture_mixer(codec);
3706
3707 if (!spec->no_analog) {
3708 err = snd_hda_attach_beep_device(codec, 0x1);
3709 if (err < 0) {
3710 alc_free(codec);
3711 return err;
3712 }
3713 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3714 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003715
3716 spec->vmaster_nid = 0x0c;
3717
3718 codec->patch_ops = alc_patch_ops;
3719 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003720 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003721#ifdef CONFIG_SND_HDA_POWER_SAVE
3722 if (!spec->loopback.amplist)
3723 spec->loopback.amplist = alc880_loopbacks;
3724#endif
3725
3726 return 0;
3727}
3728
3729
3730/*
3731 * ALC260 support
3732 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003733static int alc260_parse_auto_config(struct hda_codec *codec)
3734{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003735 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003736 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
3737 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003738}
3739
Takashi Iwai1d045db2011-07-07 18:23:21 +02003740#ifdef CONFIG_SND_HDA_POWER_SAVE
3741static const struct hda_amp_list alc260_loopbacks[] = {
3742 { 0x07, HDA_INPUT, 0 },
3743 { 0x07, HDA_INPUT, 1 },
3744 { 0x07, HDA_INPUT, 2 },
3745 { 0x07, HDA_INPUT, 3 },
3746 { 0x07, HDA_INPUT, 4 },
3747 { } /* end */
3748};
3749#endif
3750
3751/*
3752 * Pin config fixes
3753 */
3754enum {
3755 PINFIX_HP_DC5750,
3756};
3757
3758static const struct alc_fixup alc260_fixups[] = {
3759 [PINFIX_HP_DC5750] = {
3760 .type = ALC_FIXUP_PINS,
3761 .v.pins = (const struct alc_pincfg[]) {
3762 { 0x11, 0x90130110 }, /* speaker */
3763 { }
3764 }
3765 },
3766};
3767
3768static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3769 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3770 {}
3771};
3772
3773/*
3774 */
3775#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3776#include "alc260_quirks.c"
3777#endif
3778
3779static int patch_alc260(struct hda_codec *codec)
3780{
3781 struct alc_spec *spec;
3782 int err, board_config;
3783
3784 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3785 if (spec == NULL)
3786 return -ENOMEM;
3787
3788 codec->spec = spec;
3789
3790 spec->mixer_nid = 0x07;
3791
3792 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3793 alc260_models, alc260_cfg_tbl);
3794 if (board_config < 0) {
3795 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3796 codec->chip_name);
3797 board_config = ALC_MODEL_AUTO;
3798 }
3799
3800 if (board_config == ALC_MODEL_AUTO) {
3801 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3802 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3803 }
3804
3805 if (board_config == ALC_MODEL_AUTO) {
3806 /* automatic parse from the BIOS config */
3807 err = alc260_parse_auto_config(codec);
3808 if (err < 0) {
3809 alc_free(codec);
3810 return err;
3811 }
3812#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3813 else if (!err) {
3814 printk(KERN_INFO
3815 "hda_codec: Cannot set up configuration "
3816 "from BIOS. Using base mode...\n");
3817 board_config = ALC260_BASIC;
3818 }
3819#endif
3820 }
3821
Takashi Iwai1d045db2011-07-07 18:23:21 +02003822 if (board_config != ALC_MODEL_AUTO)
3823 setup_preset(codec, &alc260_presets[board_config]);
3824
Takashi Iwai60a6a842011-07-27 14:01:24 +02003825 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003826 alc_auto_fill_adc_caps(codec);
3827 alc_rebuild_imux_for_auto_mic(codec);
3828 alc_remove_invalid_adc_nids(codec);
3829 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003830
3831 if (!spec->no_analog && !spec->cap_mixer)
3832 set_capture_mixer(codec);
3833
3834 if (!spec->no_analog) {
3835 err = snd_hda_attach_beep_device(codec, 0x1);
3836 if (err < 0) {
3837 alc_free(codec);
3838 return err;
3839 }
3840 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3841 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003842
3843 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3844
3845 spec->vmaster_nid = 0x08;
3846
3847 codec->patch_ops = alc_patch_ops;
3848 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02003849 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003850 spec->shutup = alc_eapd_shutup;
3851#ifdef CONFIG_SND_HDA_POWER_SAVE
3852 if (!spec->loopback.amplist)
3853 spec->loopback.amplist = alc260_loopbacks;
3854#endif
3855
3856 return 0;
3857}
3858
3859
3860/*
3861 * ALC882/883/885/888/889 support
3862 *
3863 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3864 * configuration. Each pin widget can choose any input DACs and a mixer.
3865 * Each ADC is connected from a mixer of all inputs. This makes possible
3866 * 6-channel independent captures.
3867 *
3868 * In addition, an independent DAC for the multi-playback (not used in this
3869 * driver yet).
3870 */
3871#ifdef CONFIG_SND_HDA_POWER_SAVE
3872#define alc882_loopbacks alc880_loopbacks
3873#endif
3874
3875/*
3876 * Pin config fixes
3877 */
3878enum {
3879 PINFIX_ABIT_AW9D_MAX,
3880 PINFIX_LENOVO_Y530,
3881 PINFIX_PB_M5210,
3882 PINFIX_ACER_ASPIRE_7736,
3883};
3884
3885static const struct alc_fixup alc882_fixups[] = {
3886 [PINFIX_ABIT_AW9D_MAX] = {
3887 .type = ALC_FIXUP_PINS,
3888 .v.pins = (const struct alc_pincfg[]) {
3889 { 0x15, 0x01080104 }, /* side */
3890 { 0x16, 0x01011012 }, /* rear */
3891 { 0x17, 0x01016011 }, /* clfe */
3892 { }
3893 }
3894 },
3895 [PINFIX_LENOVO_Y530] = {
3896 .type = ALC_FIXUP_PINS,
3897 .v.pins = (const struct alc_pincfg[]) {
3898 { 0x15, 0x99130112 }, /* rear int speakers */
3899 { 0x16, 0x99130111 }, /* subwoofer */
3900 { }
3901 }
3902 },
3903 [PINFIX_PB_M5210] = {
3904 .type = ALC_FIXUP_VERBS,
3905 .v.verbs = (const struct hda_verb[]) {
3906 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
3907 {}
3908 }
3909 },
3910 [PINFIX_ACER_ASPIRE_7736] = {
3911 .type = ALC_FIXUP_SKU,
3912 .v.sku = ALC_FIXUP_SKU_IGNORE,
3913 },
3914};
3915
3916static const struct snd_pci_quirk alc882_fixup_tbl[] = {
3917 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
3918 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
3919 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
3920 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
3921 {}
3922};
3923
3924/*
3925 * BIOS auto configuration
3926 */
3927/* almost identical with ALC880 parser... */
3928static int alc882_parse_auto_config(struct hda_codec *codec)
3929{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003930 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003931 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3932 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003933}
3934
Takashi Iwai1d045db2011-07-07 18:23:21 +02003935/*
3936 */
3937#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3938#include "alc882_quirks.c"
3939#endif
3940
3941static int patch_alc882(struct hda_codec *codec)
3942{
3943 struct alc_spec *spec;
3944 int err, board_config;
3945
3946 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3947 if (spec == NULL)
3948 return -ENOMEM;
3949
3950 codec->spec = spec;
3951
3952 spec->mixer_nid = 0x0b;
3953
3954 switch (codec->vendor_id) {
3955 case 0x10ec0882:
3956 case 0x10ec0885:
3957 break;
3958 default:
3959 /* ALC883 and variants */
3960 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
3961 break;
3962 }
3963
3964 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
3965 alc882_models, alc882_cfg_tbl);
3966
3967 if (board_config < 0)
3968 board_config = alc_board_codec_sid_config(codec,
3969 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
3970
3971 if (board_config < 0) {
3972 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3973 codec->chip_name);
3974 board_config = ALC_MODEL_AUTO;
3975 }
3976
3977 if (board_config == ALC_MODEL_AUTO) {
3978 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
3979 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3980 }
3981
3982 alc_auto_parse_customize_define(codec);
3983
3984 if (board_config == ALC_MODEL_AUTO) {
3985 /* automatic parse from the BIOS config */
3986 err = alc882_parse_auto_config(codec);
3987 if (err < 0) {
3988 alc_free(codec);
3989 return err;
3990 }
3991#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3992 else if (!err) {
3993 printk(KERN_INFO
3994 "hda_codec: Cannot set up configuration "
3995 "from BIOS. Using base mode...\n");
3996 board_config = ALC882_3ST_DIG;
3997 }
3998#endif
3999 }
4000
Takashi Iwai1d045db2011-07-07 18:23:21 +02004001 if (board_config != ALC_MODEL_AUTO)
4002 setup_preset(codec, &alc882_presets[board_config]);
4003
Takashi Iwai60a6a842011-07-27 14:01:24 +02004004 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004005 alc_auto_fill_adc_caps(codec);
4006 alc_rebuild_imux_for_auto_mic(codec);
4007 alc_remove_invalid_adc_nids(codec);
4008 }
4009
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004010 if (!spec->no_analog && !spec->cap_mixer)
4011 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004012
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004013 if (!spec->no_analog && has_cdefine_beep(codec)) {
4014 err = snd_hda_attach_beep_device(codec, 0x1);
4015 if (err < 0) {
4016 alc_free(codec);
4017 return err;
4018 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004019 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004020 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004021
4022 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4023
4024 spec->vmaster_nid = 0x0c;
4025
4026 codec->patch_ops = alc_patch_ops;
4027 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004028 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004029
4030 alc_init_jacks(codec);
4031#ifdef CONFIG_SND_HDA_POWER_SAVE
4032 if (!spec->loopback.amplist)
4033 spec->loopback.amplist = alc882_loopbacks;
4034#endif
4035
4036 return 0;
4037}
4038
4039
4040/*
4041 * ALC262 support
4042 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004043static int alc262_parse_auto_config(struct hda_codec *codec)
4044{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004045 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004046 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4047 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004048}
4049
4050/*
4051 * Pin config fixes
4052 */
4053enum {
4054 PINFIX_FSC_H270,
4055 PINFIX_HP_Z200,
4056};
4057
4058static const struct alc_fixup alc262_fixups[] = {
4059 [PINFIX_FSC_H270] = {
4060 .type = ALC_FIXUP_PINS,
4061 .v.pins = (const struct alc_pincfg[]) {
4062 { 0x14, 0x99130110 }, /* speaker */
4063 { 0x15, 0x0221142f }, /* front HP */
4064 { 0x1b, 0x0121141f }, /* rear HP */
4065 { }
4066 }
4067 },
4068 [PINFIX_HP_Z200] = {
4069 .type = ALC_FIXUP_PINS,
4070 .v.pins = (const struct alc_pincfg[]) {
4071 { 0x16, 0x99130120 }, /* internal speaker */
4072 { }
4073 }
4074 },
4075};
4076
4077static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4078 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4079 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4080 {}
4081};
4082
4083
4084#ifdef CONFIG_SND_HDA_POWER_SAVE
4085#define alc262_loopbacks alc880_loopbacks
4086#endif
4087
Takashi Iwai1d045db2011-07-07 18:23:21 +02004088/*
4089 */
4090#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4091#include "alc262_quirks.c"
4092#endif
4093
4094static int patch_alc262(struct hda_codec *codec)
4095{
4096 struct alc_spec *spec;
4097 int board_config;
4098 int err;
4099
4100 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4101 if (spec == NULL)
4102 return -ENOMEM;
4103
4104 codec->spec = spec;
4105
4106 spec->mixer_nid = 0x0b;
4107
4108#if 0
4109 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4110 * under-run
4111 */
4112 {
4113 int tmp;
4114 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4115 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4116 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4117 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4118 }
4119#endif
4120 alc_auto_parse_customize_define(codec);
4121
4122 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4123
4124 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4125 alc262_models, alc262_cfg_tbl);
4126
4127 if (board_config < 0) {
4128 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4129 codec->chip_name);
4130 board_config = ALC_MODEL_AUTO;
4131 }
4132
4133 if (board_config == ALC_MODEL_AUTO) {
4134 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4135 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4136 }
4137
4138 if (board_config == ALC_MODEL_AUTO) {
4139 /* automatic parse from the BIOS config */
4140 err = alc262_parse_auto_config(codec);
4141 if (err < 0) {
4142 alc_free(codec);
4143 return err;
4144 }
4145#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4146 else if (!err) {
4147 printk(KERN_INFO
4148 "hda_codec: Cannot set up configuration "
4149 "from BIOS. Using base mode...\n");
4150 board_config = ALC262_BASIC;
4151 }
4152#endif
4153 }
4154
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004155 if (board_config != ALC_MODEL_AUTO)
4156 setup_preset(codec, &alc262_presets[board_config]);
4157
Takashi Iwai60a6a842011-07-27 14:01:24 +02004158 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004159 alc_auto_fill_adc_caps(codec);
4160 alc_rebuild_imux_for_auto_mic(codec);
4161 alc_remove_invalid_adc_nids(codec);
4162 }
4163
4164 if (!spec->no_analog && !spec->cap_mixer)
4165 set_capture_mixer(codec);
4166
Takashi Iwai1d045db2011-07-07 18:23:21 +02004167 if (!spec->no_analog && has_cdefine_beep(codec)) {
4168 err = snd_hda_attach_beep_device(codec, 0x1);
4169 if (err < 0) {
4170 alc_free(codec);
4171 return err;
4172 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004173 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004174 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004175
4176 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4177
4178 spec->vmaster_nid = 0x0c;
4179
4180 codec->patch_ops = alc_patch_ops;
4181 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004182 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004183 spec->shutup = alc_eapd_shutup;
4184
4185 alc_init_jacks(codec);
4186#ifdef CONFIG_SND_HDA_POWER_SAVE
4187 if (!spec->loopback.amplist)
4188 spec->loopback.amplist = alc262_loopbacks;
4189#endif
4190
4191 return 0;
4192}
4193
4194/*
4195 * ALC268
4196 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004197/* bind Beep switches of both NID 0x0f and 0x10 */
4198static const struct hda_bind_ctls alc268_bind_beep_sw = {
4199 .ops = &snd_hda_bind_sw,
4200 .values = {
4201 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4202 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4203 0
4204 },
4205};
4206
4207static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4208 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4209 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4210 { }
4211};
4212
4213/* set PCBEEP vol = 0, mute connections */
4214static const struct hda_verb alc268_beep_init_verbs[] = {
4215 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4216 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4217 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4218 { }
4219};
4220
4221/*
4222 * BIOS auto configuration
4223 */
4224static int alc268_parse_auto_config(struct hda_codec *codec)
4225{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004226 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004227 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004228 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4229 if (err > 0) {
4230 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4231 add_mixer(spec, alc268_beep_mixer);
4232 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004233 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004234 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004235 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004236}
4237
Takashi Iwai1d045db2011-07-07 18:23:21 +02004238/*
4239 */
4240#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4241#include "alc268_quirks.c"
4242#endif
4243
4244static int patch_alc268(struct hda_codec *codec)
4245{
4246 struct alc_spec *spec;
4247 int board_config;
4248 int i, has_beep, err;
4249
4250 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4251 if (spec == NULL)
4252 return -ENOMEM;
4253
4254 codec->spec = spec;
4255
4256 /* ALC268 has no aa-loopback mixer */
4257
4258 board_config = alc_board_config(codec, ALC268_MODEL_LAST,
4259 alc268_models, alc268_cfg_tbl);
4260
4261 if (board_config < 0)
4262 board_config = alc_board_codec_sid_config(codec,
4263 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
4264
4265 if (board_config < 0) {
4266 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4267 codec->chip_name);
4268 board_config = ALC_MODEL_AUTO;
4269 }
4270
4271 if (board_config == ALC_MODEL_AUTO) {
4272 /* automatic parse from the BIOS config */
4273 err = alc268_parse_auto_config(codec);
4274 if (err < 0) {
4275 alc_free(codec);
4276 return err;
4277 }
4278#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4279 else if (!err) {
4280 printk(KERN_INFO
4281 "hda_codec: Cannot set up configuration "
4282 "from BIOS. Using base mode...\n");
4283 board_config = ALC268_3ST;
4284 }
4285#endif
4286 }
4287
4288 if (board_config != ALC_MODEL_AUTO)
4289 setup_preset(codec, &alc268_presets[board_config]);
4290
4291 has_beep = 0;
4292 for (i = 0; i < spec->num_mixers; i++) {
4293 if (spec->mixers[i] == alc268_beep_mixer) {
4294 has_beep = 1;
4295 break;
4296 }
4297 }
4298
4299 if (has_beep) {
4300 err = snd_hda_attach_beep_device(codec, 0x1);
4301 if (err < 0) {
4302 alc_free(codec);
4303 return err;
4304 }
4305 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4306 /* override the amp caps for beep generator */
4307 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4308 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4309 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4310 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4311 (0 << AC_AMPCAP_MUTE_SHIFT));
4312 }
4313
Takashi Iwai60a6a842011-07-27 14:01:24 +02004314 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004315 alc_auto_fill_adc_caps(codec);
4316 alc_rebuild_imux_for_auto_mic(codec);
4317 alc_remove_invalid_adc_nids(codec);
4318 }
4319
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004320 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004321 set_capture_mixer(codec);
4322
4323 spec->vmaster_nid = 0x02;
4324
4325 codec->patch_ops = alc_patch_ops;
4326 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004327 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004328 spec->shutup = alc_eapd_shutup;
4329
4330 alc_init_jacks(codec);
4331
4332 return 0;
4333}
4334
4335/*
4336 * ALC269
4337 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004338#ifdef CONFIG_SND_HDA_POWER_SAVE
4339#define alc269_loopbacks alc880_loopbacks
4340#endif
4341
4342static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4343 .substreams = 1,
4344 .channels_min = 2,
4345 .channels_max = 8,
4346 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4347 /* NID is set in alc_build_pcms */
4348 .ops = {
4349 .open = alc_playback_pcm_open,
4350 .prepare = alc_playback_pcm_prepare,
4351 .cleanup = alc_playback_pcm_cleanup
4352 },
4353};
4354
4355static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4356 .substreams = 1,
4357 .channels_min = 2,
4358 .channels_max = 2,
4359 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4360 /* NID is set in alc_build_pcms */
4361};
4362
4363#ifdef CONFIG_SND_HDA_POWER_SAVE
4364static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4365{
4366 switch (codec->subsystem_id) {
4367 case 0x103c1586:
4368 return 1;
4369 }
4370 return 0;
4371}
4372
4373static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4374{
4375 /* update mute-LED according to the speaker mute state */
4376 if (nid == 0x01 || nid == 0x14) {
4377 int pinval;
4378 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4379 HDA_AMP_MUTE)
4380 pinval = 0x24;
4381 else
4382 pinval = 0x20;
4383 /* mic2 vref pin is used for mute LED control */
4384 snd_hda_codec_update_cache(codec, 0x19, 0,
4385 AC_VERB_SET_PIN_WIDGET_CONTROL,
4386 pinval);
4387 }
4388 return alc_check_power_status(codec, nid);
4389}
4390#endif /* CONFIG_SND_HDA_POWER_SAVE */
4391
4392/* different alc269-variants */
4393enum {
4394 ALC269_TYPE_ALC269VA,
4395 ALC269_TYPE_ALC269VB,
4396 ALC269_TYPE_ALC269VC,
4397};
4398
4399/*
4400 * BIOS auto configuration
4401 */
4402static int alc269_parse_auto_config(struct hda_codec *codec)
4403{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004404 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004405 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
4406 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4407 struct alc_spec *spec = codec->spec;
4408 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
4409 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004410
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004411 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004412}
4413
Takashi Iwai1d045db2011-07-07 18:23:21 +02004414static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4415{
4416 int val = alc_read_coef_idx(codec, 0x04);
4417 if (power_up)
4418 val |= 1 << 11;
4419 else
4420 val &= ~(1 << 11);
4421 alc_write_coef_idx(codec, 0x04, val);
4422}
4423
4424static void alc269_shutup(struct hda_codec *codec)
4425{
4426 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4427 alc269_toggle_power_output(codec, 0);
4428 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4429 alc269_toggle_power_output(codec, 0);
4430 msleep(150);
4431 }
4432}
4433
Takashi Iwai2a439522011-07-26 09:52:50 +02004434#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004435static int alc269_resume(struct hda_codec *codec)
4436{
4437 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4438 alc269_toggle_power_output(codec, 0);
4439 msleep(150);
4440 }
4441
4442 codec->patch_ops.init(codec);
4443
4444 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4445 alc269_toggle_power_output(codec, 1);
4446 msleep(200);
4447 }
4448
4449 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4450 alc269_toggle_power_output(codec, 1);
4451
4452 snd_hda_codec_resume_amp(codec);
4453 snd_hda_codec_resume_cache(codec);
4454 hda_call_check_power_status(codec, 0x01);
4455 return 0;
4456}
Takashi Iwai2a439522011-07-26 09:52:50 +02004457#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004458
4459static void alc269_fixup_hweq(struct hda_codec *codec,
4460 const struct alc_fixup *fix, int action)
4461{
4462 int coef;
4463
4464 if (action != ALC_FIXUP_ACT_INIT)
4465 return;
4466 coef = alc_read_coef_idx(codec, 0x1e);
4467 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4468}
4469
4470static void alc271_fixup_dmic(struct hda_codec *codec,
4471 const struct alc_fixup *fix, int action)
4472{
4473 static const struct hda_verb verbs[] = {
4474 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4475 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4476 {}
4477 };
4478 unsigned int cfg;
4479
4480 if (strcmp(codec->chip_name, "ALC271X"))
4481 return;
4482 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4483 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4484 snd_hda_sequence_write(codec, verbs);
4485}
4486
Takashi Iwai017f2a12011-07-09 14:42:25 +02004487static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4488 const struct alc_fixup *fix, int action)
4489{
4490 struct alc_spec *spec = codec->spec;
4491
4492 if (action != ALC_FIXUP_ACT_PROBE)
4493 return;
4494
4495 /* Due to a hardware problem on Lenovo Ideadpad, we need to
4496 * fix the sample rate of analog I/O to 44.1kHz
4497 */
4498 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
4499 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4500}
4501
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004502static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4503 const struct alc_fixup *fix, int action)
4504{
4505 int coef;
4506
4507 if (action != ALC_FIXUP_ACT_INIT)
4508 return;
4509 /* The digital-mic unit sends PDM (differential signal) instead of
4510 * the standard PCM, thus you can't record a valid mono stream as is.
4511 * Below is a workaround specific to ALC269 to control the dmic
4512 * signal source as mono.
4513 */
4514 coef = alc_read_coef_idx(codec, 0x07);
4515 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4516}
4517
Takashi Iwai1d045db2011-07-07 18:23:21 +02004518enum {
4519 ALC269_FIXUP_SONY_VAIO,
4520 ALC275_FIXUP_SONY_VAIO_GPIO2,
4521 ALC269_FIXUP_DELL_M101Z,
4522 ALC269_FIXUP_SKU_IGNORE,
4523 ALC269_FIXUP_ASUS_G73JW,
4524 ALC269_FIXUP_LENOVO_EAPD,
4525 ALC275_FIXUP_SONY_HWEQ,
4526 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004527 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004528 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004529};
4530
4531static const struct alc_fixup alc269_fixups[] = {
4532 [ALC269_FIXUP_SONY_VAIO] = {
4533 .type = ALC_FIXUP_VERBS,
4534 .v.verbs = (const struct hda_verb[]) {
4535 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4536 {}
4537 }
4538 },
4539 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4540 .type = ALC_FIXUP_VERBS,
4541 .v.verbs = (const struct hda_verb[]) {
4542 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4543 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4544 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4545 { }
4546 },
4547 .chained = true,
4548 .chain_id = ALC269_FIXUP_SONY_VAIO
4549 },
4550 [ALC269_FIXUP_DELL_M101Z] = {
4551 .type = ALC_FIXUP_VERBS,
4552 .v.verbs = (const struct hda_verb[]) {
4553 /* Enables internal speaker */
4554 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4555 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4556 {}
4557 }
4558 },
4559 [ALC269_FIXUP_SKU_IGNORE] = {
4560 .type = ALC_FIXUP_SKU,
4561 .v.sku = ALC_FIXUP_SKU_IGNORE,
4562 },
4563 [ALC269_FIXUP_ASUS_G73JW] = {
4564 .type = ALC_FIXUP_PINS,
4565 .v.pins = (const struct alc_pincfg[]) {
4566 { 0x17, 0x99130111 }, /* subwoofer */
4567 { }
4568 }
4569 },
4570 [ALC269_FIXUP_LENOVO_EAPD] = {
4571 .type = ALC_FIXUP_VERBS,
4572 .v.verbs = (const struct hda_verb[]) {
4573 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4574 {}
4575 }
4576 },
4577 [ALC275_FIXUP_SONY_HWEQ] = {
4578 .type = ALC_FIXUP_FUNC,
4579 .v.func = alc269_fixup_hweq,
4580 .chained = true,
4581 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4582 },
4583 [ALC271_FIXUP_DMIC] = {
4584 .type = ALC_FIXUP_FUNC,
4585 .v.func = alc271_fixup_dmic,
4586 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004587 [ALC269_FIXUP_PCM_44K] = {
4588 .type = ALC_FIXUP_FUNC,
4589 .v.func = alc269_fixup_pcm_44k,
4590 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004591 [ALC269_FIXUP_STEREO_DMIC] = {
4592 .type = ALC_FIXUP_FUNC,
4593 .v.func = alc269_fixup_stereo_dmic,
4594 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004595};
4596
4597static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02004598 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004599 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4600 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4601 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4602 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4603 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004604 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4605 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4606 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4607 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4608 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4609 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
4610 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4611 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4612 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4613 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4614 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02004615 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004616 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
4617 {}
4618};
4619
4620
4621static int alc269_fill_coef(struct hda_codec *codec)
4622{
4623 int val;
4624
4625 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4626 alc_write_coef_idx(codec, 0xf, 0x960b);
4627 alc_write_coef_idx(codec, 0xe, 0x8817);
4628 }
4629
4630 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4631 alc_write_coef_idx(codec, 0xf, 0x960b);
4632 alc_write_coef_idx(codec, 0xe, 0x8814);
4633 }
4634
4635 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4636 val = alc_read_coef_idx(codec, 0x04);
4637 /* Power up output pin */
4638 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4639 }
4640
4641 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4642 val = alc_read_coef_idx(codec, 0xd);
4643 if ((val & 0x0c00) >> 10 != 0x1) {
4644 /* Capless ramp up clock control */
4645 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4646 }
4647 val = alc_read_coef_idx(codec, 0x17);
4648 if ((val & 0x01c0) >> 6 != 0x4) {
4649 /* Class D power on reset */
4650 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4651 }
4652 }
4653
4654 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4655 alc_write_coef_idx(codec, 0xd, val | (1<<14));
4656
4657 val = alc_read_coef_idx(codec, 0x4); /* HP */
4658 alc_write_coef_idx(codec, 0x4, val | (1<<11));
4659
4660 return 0;
4661}
4662
4663/*
4664 */
4665#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4666#include "alc269_quirks.c"
4667#endif
4668
4669static int patch_alc269(struct hda_codec *codec)
4670{
4671 struct alc_spec *spec;
4672 int board_config, coef;
4673 int err;
4674
4675 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4676 if (spec == NULL)
4677 return -ENOMEM;
4678
4679 codec->spec = spec;
4680
4681 spec->mixer_nid = 0x0b;
4682
4683 alc_auto_parse_customize_define(codec);
4684
4685 if (codec->vendor_id == 0x10ec0269) {
4686 spec->codec_variant = ALC269_TYPE_ALC269VA;
4687 coef = alc_read_coef_idx(codec, 0);
4688 if ((coef & 0x00f0) == 0x0010) {
4689 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
4690 spec->cdefine.platform_type == 1) {
4691 alc_codec_rename(codec, "ALC271X");
4692 } else if ((coef & 0xf000) == 0x2000) {
4693 alc_codec_rename(codec, "ALC259");
4694 } else if ((coef & 0xf000) == 0x3000) {
4695 alc_codec_rename(codec, "ALC258");
4696 } else if ((coef & 0xfff0) == 0x3010) {
4697 alc_codec_rename(codec, "ALC277");
4698 } else {
4699 alc_codec_rename(codec, "ALC269VB");
4700 }
4701 spec->codec_variant = ALC269_TYPE_ALC269VB;
4702 } else if ((coef & 0x00f0) == 0x0020) {
4703 if (coef == 0xa023)
4704 alc_codec_rename(codec, "ALC259");
4705 else if (coef == 0x6023)
4706 alc_codec_rename(codec, "ALC281X");
4707 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4708 codec->bus->pci->subsystem_device == 0x21f3)
4709 alc_codec_rename(codec, "ALC3202");
4710 else
4711 alc_codec_rename(codec, "ALC269VC");
4712 spec->codec_variant = ALC269_TYPE_ALC269VC;
4713 } else
4714 alc_fix_pll_init(codec, 0x20, 0x04, 15);
4715 alc269_fill_coef(codec);
4716 }
4717
4718 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
4719 alc269_models, alc269_cfg_tbl);
4720
4721 if (board_config < 0) {
4722 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4723 codec->chip_name);
4724 board_config = ALC_MODEL_AUTO;
4725 }
4726
4727 if (board_config == ALC_MODEL_AUTO) {
4728 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
4729 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4730 }
4731
4732 if (board_config == ALC_MODEL_AUTO) {
4733 /* automatic parse from the BIOS config */
4734 err = alc269_parse_auto_config(codec);
4735 if (err < 0) {
4736 alc_free(codec);
4737 return err;
4738 }
4739#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4740 else if (!err) {
4741 printk(KERN_INFO
4742 "hda_codec: Cannot set up configuration "
4743 "from BIOS. Using base mode...\n");
4744 board_config = ALC269_BASIC;
4745 }
4746#endif
4747 }
4748
Takashi Iwai1d045db2011-07-07 18:23:21 +02004749 if (board_config != ALC_MODEL_AUTO)
4750 setup_preset(codec, &alc269_presets[board_config]);
4751
Takashi Iwai60a6a842011-07-27 14:01:24 +02004752 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004753 alc_auto_fill_adc_caps(codec);
4754 alc_rebuild_imux_for_auto_mic(codec);
4755 alc_remove_invalid_adc_nids(codec);
4756 }
4757
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004758 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004759 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004760
4761 if (!spec->no_analog && has_cdefine_beep(codec)) {
4762 err = snd_hda_attach_beep_device(codec, 0x1);
4763 if (err < 0) {
4764 alc_free(codec);
4765 return err;
4766 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004767 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004768 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004769
4770 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4771
4772 spec->vmaster_nid = 0x02;
4773
4774 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02004775#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004776 codec->patch_ops.resume = alc269_resume;
4777#endif
4778 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004779 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004780 spec->shutup = alc269_shutup;
4781
4782 alc_init_jacks(codec);
4783#ifdef CONFIG_SND_HDA_POWER_SAVE
4784 if (!spec->loopback.amplist)
4785 spec->loopback.amplist = alc269_loopbacks;
4786 if (alc269_mic2_for_mute_led(codec))
4787 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
4788#endif
4789
4790 return 0;
4791}
4792
4793/*
4794 * ALC861
4795 */
4796
Takashi Iwai1d045db2011-07-07 18:23:21 +02004797static int alc861_parse_auto_config(struct hda_codec *codec)
4798{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004799 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004800 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4801 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004802}
4803
Takashi Iwai1d045db2011-07-07 18:23:21 +02004804#ifdef CONFIG_SND_HDA_POWER_SAVE
4805static const struct hda_amp_list alc861_loopbacks[] = {
4806 { 0x15, HDA_INPUT, 0 },
4807 { 0x15, HDA_INPUT, 1 },
4808 { 0x15, HDA_INPUT, 2 },
4809 { 0x15, HDA_INPUT, 3 },
4810 { } /* end */
4811};
4812#endif
4813
4814
4815/* Pin config fixes */
4816enum {
4817 PINFIX_FSC_AMILO_PI1505,
4818};
4819
4820static const struct alc_fixup alc861_fixups[] = {
4821 [PINFIX_FSC_AMILO_PI1505] = {
4822 .type = ALC_FIXUP_PINS,
4823 .v.pins = (const struct alc_pincfg[]) {
4824 { 0x0b, 0x0221101f }, /* HP */
4825 { 0x0f, 0x90170310 }, /* speaker */
4826 { }
4827 }
4828 },
4829};
4830
4831static const struct snd_pci_quirk alc861_fixup_tbl[] = {
4832 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
4833 {}
4834};
4835
4836/*
4837 */
4838#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4839#include "alc861_quirks.c"
4840#endif
4841
4842static int patch_alc861(struct hda_codec *codec)
4843{
4844 struct alc_spec *spec;
4845 int board_config;
4846 int err;
4847
4848 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4849 if (spec == NULL)
4850 return -ENOMEM;
4851
4852 codec->spec = spec;
4853
4854 spec->mixer_nid = 0x15;
4855
4856 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
4857 alc861_models, alc861_cfg_tbl);
4858
4859 if (board_config < 0) {
4860 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4861 codec->chip_name);
4862 board_config = ALC_MODEL_AUTO;
4863 }
4864
4865 if (board_config == ALC_MODEL_AUTO) {
4866 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
4867 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4868 }
4869
4870 if (board_config == ALC_MODEL_AUTO) {
4871 /* automatic parse from the BIOS config */
4872 err = alc861_parse_auto_config(codec);
4873 if (err < 0) {
4874 alc_free(codec);
4875 return err;
4876 }
4877#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4878 else if (!err) {
4879 printk(KERN_INFO
4880 "hda_codec: Cannot set up configuration "
4881 "from BIOS. Using base mode...\n");
4882 board_config = ALC861_3ST_DIG;
4883 }
4884#endif
4885 }
4886
Takashi Iwai1d045db2011-07-07 18:23:21 +02004887 if (board_config != ALC_MODEL_AUTO)
4888 setup_preset(codec, &alc861_presets[board_config]);
4889
Takashi Iwai60a6a842011-07-27 14:01:24 +02004890 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004891 alc_auto_fill_adc_caps(codec);
4892 alc_rebuild_imux_for_auto_mic(codec);
4893 alc_remove_invalid_adc_nids(codec);
4894 }
4895
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004896 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004897 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004898
4899 if (!spec->no_analog) {
4900 err = snd_hda_attach_beep_device(codec, 0x23);
4901 if (err < 0) {
4902 alc_free(codec);
4903 return err;
4904 }
4905 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
4906 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004907
4908 spec->vmaster_nid = 0x03;
4909
4910 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4911
4912 codec->patch_ops = alc_patch_ops;
4913 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02004914 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004915#ifdef CONFIG_SND_HDA_POWER_SAVE
4916 spec->power_hook = alc_power_eapd;
4917#endif
4918 }
4919#ifdef CONFIG_SND_HDA_POWER_SAVE
4920 if (!spec->loopback.amplist)
4921 spec->loopback.amplist = alc861_loopbacks;
4922#endif
4923
4924 return 0;
4925}
4926
4927/*
4928 * ALC861-VD support
4929 *
4930 * Based on ALC882
4931 *
4932 * In addition, an independent DAC
4933 */
4934#ifdef CONFIG_SND_HDA_POWER_SAVE
4935#define alc861vd_loopbacks alc880_loopbacks
4936#endif
4937
Takashi Iwai1d045db2011-07-07 18:23:21 +02004938static int alc861vd_parse_auto_config(struct hda_codec *codec)
4939{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004940 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004941 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4942 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004943}
4944
Takashi Iwai1d045db2011-07-07 18:23:21 +02004945enum {
4946 ALC660VD_FIX_ASUS_GPIO1
4947};
4948
4949/* reset GPIO1 */
4950static const struct alc_fixup alc861vd_fixups[] = {
4951 [ALC660VD_FIX_ASUS_GPIO1] = {
4952 .type = ALC_FIXUP_VERBS,
4953 .v.verbs = (const struct hda_verb[]) {
4954 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
4955 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4956 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4957 { }
4958 }
4959 },
4960};
4961
4962static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
4963 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
4964 {}
4965};
4966
4967static const struct hda_verb alc660vd_eapd_verbs[] = {
4968 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
4969 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
4970 { }
4971};
4972
4973/*
4974 */
4975#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4976#include "alc861vd_quirks.c"
4977#endif
4978
4979static int patch_alc861vd(struct hda_codec *codec)
4980{
4981 struct alc_spec *spec;
4982 int err, board_config;
4983
4984 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4985 if (spec == NULL)
4986 return -ENOMEM;
4987
4988 codec->spec = spec;
4989
4990 spec->mixer_nid = 0x0b;
4991
4992 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
4993 alc861vd_models, alc861vd_cfg_tbl);
4994
4995 if (board_config < 0) {
4996 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4997 codec->chip_name);
4998 board_config = ALC_MODEL_AUTO;
4999 }
5000
5001 if (board_config == ALC_MODEL_AUTO) {
5002 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
5003 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5004 }
5005
5006 if (board_config == ALC_MODEL_AUTO) {
5007 /* automatic parse from the BIOS config */
5008 err = alc861vd_parse_auto_config(codec);
5009 if (err < 0) {
5010 alc_free(codec);
5011 return err;
5012 }
5013#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5014 else if (!err) {
5015 printk(KERN_INFO
5016 "hda_codec: Cannot set up configuration "
5017 "from BIOS. Using base mode...\n");
5018 board_config = ALC861VD_3ST;
5019 }
5020#endif
5021 }
5022
Takashi Iwai1d045db2011-07-07 18:23:21 +02005023 if (board_config != ALC_MODEL_AUTO)
5024 setup_preset(codec, &alc861vd_presets[board_config]);
5025
5026 if (codec->vendor_id == 0x10ec0660) {
5027 /* always turn on EAPD */
5028 add_verb(spec, alc660vd_eapd_verbs);
5029 }
5030
Takashi Iwai60a6a842011-07-27 14:01:24 +02005031 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005032 alc_auto_fill_adc_caps(codec);
5033 alc_rebuild_imux_for_auto_mic(codec);
5034 alc_remove_invalid_adc_nids(codec);
5035 }
5036
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005037 if (!spec->no_analog && !spec->cap_mixer)
5038 set_capture_mixer(codec);
5039
5040 if (!spec->no_analog) {
5041 err = snd_hda_attach_beep_device(codec, 0x23);
5042 if (err < 0) {
5043 alc_free(codec);
5044 return err;
5045 }
5046 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5047 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005048
5049 spec->vmaster_nid = 0x02;
5050
5051 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5052
5053 codec->patch_ops = alc_patch_ops;
5054
5055 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005056 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005057 spec->shutup = alc_eapd_shutup;
5058#ifdef CONFIG_SND_HDA_POWER_SAVE
5059 if (!spec->loopback.amplist)
5060 spec->loopback.amplist = alc861vd_loopbacks;
5061#endif
5062
5063 return 0;
5064}
5065
5066/*
5067 * ALC662 support
5068 *
5069 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5070 * configuration. Each pin widget can choose any input DACs and a mixer.
5071 * Each ADC is connected from a mixer of all inputs. This makes possible
5072 * 6-channel independent captures.
5073 *
5074 * In addition, an independent DAC for the multi-playback (not used in this
5075 * driver yet).
5076 */
5077#ifdef CONFIG_SND_HDA_POWER_SAVE
5078#define alc662_loopbacks alc880_loopbacks
5079#endif
5080
5081/*
5082 * BIOS auto configuration
5083 */
5084
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005085static int alc662_parse_auto_config(struct hda_codec *codec)
5086{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005087 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005088 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5089 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5090 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005091
Kailang Yang6227cdc2010-02-25 08:36:52 +01005092 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5093 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005094 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005095 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005096 ssids = alc662_ssids;
5097 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005098}
5099
Todd Broch6be79482010-12-07 16:51:05 -08005100static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005101 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005102{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005103 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005104 return;
Todd Broch6be79482010-12-07 16:51:05 -08005105 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5106 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5107 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5108 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5109 (0 << AC_AMPCAP_MUTE_SHIFT)))
5110 printk(KERN_WARNING
5111 "hda_codec: failed to override amp caps for NID 0x2\n");
5112}
5113
David Henningsson6cb3b702010-09-09 08:51:44 +02005114enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005115 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005116 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005117 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005118 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005119 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005120 ALC662_FIXUP_HP_RP5800,
David Henningsson6cb3b702010-09-09 08:51:44 +02005121};
5122
5123static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005124 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005125 .type = ALC_FIXUP_PINS,
5126 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005127 { 0x15, 0x99130112 }, /* subwoofer */
5128 { }
5129 }
5130 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005131 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005132 .type = ALC_FIXUP_PINS,
5133 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005134 { 0x17, 0x99130112 }, /* subwoofer */
5135 { }
5136 }
5137 },
Todd Broch6be79482010-12-07 16:51:05 -08005138 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005139 .type = ALC_FIXUP_FUNC,
5140 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005141 },
5142 [ALC662_FIXUP_CZC_P10T] = {
5143 .type = ALC_FIXUP_VERBS,
5144 .v.verbs = (const struct hda_verb[]) {
5145 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5146 {}
5147 }
5148 },
David Henningsson94024cd2011-04-29 14:10:55 +02005149 [ALC662_FIXUP_SKU_IGNORE] = {
5150 .type = ALC_FIXUP_SKU,
5151 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005152 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005153 [ALC662_FIXUP_HP_RP5800] = {
5154 .type = ALC_FIXUP_PINS,
5155 .v.pins = (const struct alc_pincfg[]) {
5156 { 0x14, 0x0221201f }, /* HP out */
5157 { }
5158 },
5159 .chained = true,
5160 .chain_id = ALC662_FIXUP_SKU_IGNORE
5161 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005162};
5163
Takashi Iwaia9111322011-05-02 11:30:18 +02005164static const struct snd_pci_quirk alc662_fixup_tbl[] = {
David Henningssona6c47a82011-02-10 15:39:19 +01005165 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005166 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005167 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005168 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005169 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005170 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005171 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005172 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02005173 {}
5174};
5175
Todd Broch6be79482010-12-07 16:51:05 -08005176static const struct alc_model_fixup alc662_fixup_models[] = {
5177 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
5178 {}
5179};
David Henningsson6cb3b702010-09-09 08:51:44 +02005180
5181
Takashi Iwai1d045db2011-07-07 18:23:21 +02005182/*
5183 */
5184#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5185#include "alc662_quirks.c"
5186#endif
5187
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005188static int patch_alc662(struct hda_codec *codec)
5189{
5190 struct alc_spec *spec;
5191 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02005192 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005193
5194 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5195 if (!spec)
5196 return -ENOMEM;
5197
5198 codec->spec = spec;
5199
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005200 spec->mixer_nid = 0x0b;
5201
Kailang Yangda00c242010-03-19 11:23:45 +01005202 alc_auto_parse_customize_define(codec);
5203
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005204 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5205
Kailang Yang693194f2010-10-21 08:51:48 +02005206 coef = alc_read_coef_idx(codec, 0);
5207 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005208 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005209 else if (coef & (1 << 14) &&
5210 codec->bus->pci->subsystem_vendor == 0x1025 &&
5211 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005212 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005213 else if (coef == 0x4011)
5214 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005215
Takashi Iwai1d045db2011-07-07 18:23:21 +02005216 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
5217 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005218 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005219 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5220 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005221 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005222 }
5223
Takashi Iwai1d045db2011-07-07 18:23:21 +02005224 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005225 alc_pick_fixup(codec, alc662_fixup_models,
5226 alc662_fixup_tbl, alc662_fixups);
5227 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005228 /* automatic parse from the BIOS config */
5229 err = alc662_parse_auto_config(codec);
5230 if (err < 0) {
5231 alc_free(codec);
5232 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005233 }
5234#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5235 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005236 printk(KERN_INFO
5237 "hda_codec: Cannot set up configuration "
5238 "from BIOS. Using base mode...\n");
5239 board_config = ALC662_3ST_2ch_DIG;
5240 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005241#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005242 }
5243
Takashi Iwai1d045db2011-07-07 18:23:21 +02005244 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005245 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005246
Takashi Iwai60a6a842011-07-27 14:01:24 +02005247 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005248 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005249 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005250 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005251 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005252
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005253 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005254 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005255
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005256 if (!spec->no_analog && has_cdefine_beep(codec)) {
5257 err = snd_hda_attach_beep_device(codec, 0x1);
5258 if (err < 0) {
5259 alc_free(codec);
5260 return err;
5261 }
Kailang Yangda00c242010-03-19 11:23:45 +01005262 switch (codec->vendor_id) {
5263 case 0x10ec0662:
5264 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5265 break;
5266 case 0x10ec0272:
5267 case 0x10ec0663:
5268 case 0x10ec0665:
5269 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5270 break;
5271 case 0x10ec0273:
5272 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5273 break;
5274 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005275 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005276 spec->vmaster_nid = 0x02;
5277
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005278 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5279
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005280 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005281 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005282 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c7161532011-04-07 10:37:16 +02005283 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005284
Kailang Yangbf1b0222010-10-21 08:49:56 +02005285 alc_init_jacks(codec);
5286
Takashi Iwaicb53c622007-08-10 17:21:45 +02005287#ifdef CONFIG_SND_HDA_POWER_SAVE
5288 if (!spec->loopback.amplist)
5289 spec->loopback.amplist = alc662_loopbacks;
5290#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005291
5292 return 0;
5293}
5294
Kailang Yang274693f2009-12-03 10:07:50 +01005295static int patch_alc888(struct hda_codec *codec)
5296{
5297 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5298 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005299 if (codec->vendor_id == 0x10ec0887)
5300 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5301 else
5302 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005303 if (!codec->chip_name) {
5304 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005305 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005306 }
5307 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005308 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005309 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005310}
5311
Kailang Yangb478b992011-05-18 11:51:15 +02005312static int patch_alc899(struct hda_codec *codec)
5313{
5314 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5315 kfree(codec->chip_name);
5316 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5317 }
5318 return patch_alc882(codec);
5319}
5320
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005321/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005322 * ALC680 support
5323 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005324
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005325static int alc680_parse_auto_config(struct hda_codec *codec)
5326{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005327 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005328}
5329
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005330/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005331 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005332#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5333#include "alc680_quirks.c"
5334#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005335
5336static int patch_alc680(struct hda_codec *codec)
5337{
5338 struct alc_spec *spec;
5339 int board_config;
5340 int err;
5341
5342 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5343 if (spec == NULL)
5344 return -ENOMEM;
5345
5346 codec->spec = spec;
5347
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005348 /* ALC680 has no aa-loopback mixer */
5349
Takashi Iwai1d045db2011-07-07 18:23:21 +02005350 board_config = alc_board_config(codec, ALC680_MODEL_LAST,
5351 alc680_models, alc680_cfg_tbl);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005352
Takashi Iwai1d045db2011-07-07 18:23:21 +02005353 if (board_config < 0) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005354 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5355 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005356 board_config = ALC_MODEL_AUTO;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005357 }
5358
Takashi Iwai1d045db2011-07-07 18:23:21 +02005359 if (board_config == ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005360 /* automatic parse from the BIOS config */
5361 err = alc680_parse_auto_config(codec);
5362 if (err < 0) {
5363 alc_free(codec);
5364 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005365 }
5366#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5367 else if (!err) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005368 printk(KERN_INFO
5369 "hda_codec: Cannot set up configuration "
5370 "from BIOS. Using base mode...\n");
5371 board_config = ALC680_BASE;
5372 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005373#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005374 }
5375
Takashi Iwai1d045db2011-07-07 18:23:21 +02005376 if (board_config != ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005377 setup_preset(codec, &alc680_presets[board_config]);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005378#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
Takashi Iwai21268962011-07-07 15:01:13 +02005379 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005380#endif
Takashi Iwai21268962011-07-07 15:01:13 +02005381 }
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005382
Takashi Iwai60a6a842011-07-27 14:01:24 +02005383 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005384 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005385 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005386 alc_remove_invalid_adc_nids(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005387 }
5388
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005389 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005390 set_capture_mixer(codec);
5391
5392 spec->vmaster_nid = 0x02;
5393
5394 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005395 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005396 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005397
5398 return 0;
5399}
5400
5401/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402 * patch entries
5403 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005404static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005405 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005407 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005408 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005409 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005410 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005411 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005412 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005413 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005414 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005415 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005416 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005417 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5418 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5419 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005420 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005421 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005422 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5423 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005424 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005425 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005426 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005427 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005428 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005429 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02005430 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005431 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005432 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005433 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005434 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005435 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005436 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005437 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005438 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005439 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02005440 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005441 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005442 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443 {} /* terminator */
5444};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005445
5446MODULE_ALIAS("snd-hda-codec-id:10ec*");
5447
5448MODULE_LICENSE("GPL");
5449MODULE_DESCRIPTION("Realtek HD-audio codec");
5450
5451static struct hda_codec_preset_list realtek_list = {
5452 .preset = snd_hda_preset_realtek,
5453 .owner = THIS_MODULE,
5454};
5455
5456static int __init patch_realtek_init(void)
5457{
5458 return snd_hda_add_codec_preset(&realtek_list);
5459}
5460
5461static void __exit patch_realtek_exit(void)
5462{
5463 snd_hda_delete_codec_preset(&realtek_list);
5464}
5465
5466module_init(patch_realtek_init)
5467module_exit(patch_realtek_exit)