blob: 349acc6bdbac5b6d7793f12b45db5aa98aeed169 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
Takashi Iwai1d045db2011-07-07 18:23:21 +02004 * HD audio interface patch for Realtek ALC codecs
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Kailang Yangdf694da2005-12-05 19:42:22 +01006 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Takashi Iwai <tiwai@suse.de>
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01009 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020031#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "hda_codec.h"
33#include "hda_local.h"
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090034#include "hda_beep.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Takashi Iwai1d045db2011-07-07 18:23:21 +020036/* unsol event tags */
37#define ALC_FRONT_EVENT 0x01
38#define ALC_DCVOL_EVENT 0x02
39#define ALC_HP_EVENT 0x04
40#define ALC_MIC_EVENT 0x08
Takashi Iwaid4a86d82010-06-23 17:51:26 +020041
Kailang Yangdf694da2005-12-05 19:42:22 +010042/* for GPIO Poll */
43#define GPIO_MASK 0x03
44
Takashi Iwai4a79ba32009-04-22 16:31:35 +020045/* extra amp-initialization sequence types */
46enum {
47 ALC_INIT_NONE,
48 ALC_INIT_DEFAULT,
49 ALC_INIT_GPIO1,
50 ALC_INIT_GPIO2,
51 ALC_INIT_GPIO3,
52};
53
Kailang Yangda00c242010-03-19 11:23:45 +010054struct alc_customize_define {
55 unsigned int sku_cfg;
56 unsigned char port_connectivity;
57 unsigned char check_sum;
58 unsigned char customization;
59 unsigned char external_amp;
60 unsigned int enable_pcbeep:1;
61 unsigned int platform_type:1;
62 unsigned int swap:1;
63 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020064 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010065};
66
Takashi Iwaib5bfbc62011-01-13 14:22:32 +010067struct alc_fixup;
68
Takashi Iwaice764ab2011-04-27 16:35:23 +020069struct alc_multi_io {
70 hda_nid_t pin; /* multi-io widget pin NID */
71 hda_nid_t dac; /* DAC to be connected */
72 unsigned int ctl_in; /* cached input-pin control value */
73};
74
Takashi Iwaid922b512011-04-28 12:18:53 +020075enum {
Takashi Iwai3b8510c2011-04-28 14:03:24 +020076 ALC_AUTOMUTE_PIN, /* change the pin control */
77 ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
78 ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
Takashi Iwaid922b512011-04-28 12:18:53 +020079};
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081struct alc_spec {
82 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020083 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 unsigned int num_mixers;
Takashi Iwaia9111322011-05-02 11:30:18 +020085 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010086 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwai2d9c6482009-10-13 08:06:55 +020088 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +020089 * don't forget NULL
90 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +020091 */
92 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Takashi Iwaiaa563af2009-07-31 10:05:11 +020094 char stream_name_analog[32]; /* analog PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +020095 const struct hda_pcm_stream *stream_analog_playback;
96 const struct hda_pcm_stream *stream_analog_capture;
97 const struct hda_pcm_stream *stream_analog_alt_playback;
98 const struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200100 char stream_name_digital[32]; /* digital PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +0200101 const struct hda_pcm_stream *stream_digital_playback;
102 const struct hda_pcm_stream *stream_digital_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200105 struct hda_multi_out multiout; /* playback set-up
106 * max_channels, dacs must be set
107 * dig_out_nid and hp_nid are optional
108 */
Takashi Iwai63300792008-01-24 15:31:36 +0100109 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100110 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100111 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 /* capture */
114 unsigned int num_adc_nids;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +0200115 const hda_nid_t *adc_nids;
116 const hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200117 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Takashi Iwai1f0f4b82011-06-27 10:52:59 +0200118 hda_nid_t mixer_nid; /* analog-mixer NID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Takashi Iwai840b64c2010-07-13 22:49:01 +0200120 /* capture setup for dynamic dual-adc switch */
Takashi Iwai840b64c2010-07-13 22:49:01 +0200121 hda_nid_t cur_adc;
122 unsigned int cur_adc_stream_tag;
123 unsigned int cur_adc_format;
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200126 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 const struct hda_input_mux *input_mux;
128 unsigned int cur_mux[3];
Takashi Iwai21268962011-07-07 15:01:13 +0200129 hda_nid_t ext_mic_pin;
130 hda_nid_t dock_mic_pin;
131 hda_nid_t int_mic_pin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100134 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200136 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200137 int const_channel_count;
138 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100141 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200142
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200143 /* dynamic controls, init_verbs and input_mux */
144 struct auto_pin_cfg autocfg;
Kailang Yangda00c242010-03-19 11:23:45 +0100145 struct alc_customize_define cdefine;
Takashi Iwai603c4012008-07-30 15:01:44 +0200146 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200147 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200148 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi 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 Iwai1c716152011-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 */
171 unsigned int automute_lines:1; /* automute line-out as well */
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 Iwai1a1455d2011-04-28 17:36:18 +0200554 if (!spec->automute_lines || !spec->automute)
555 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
568 if (!spec->automute)
569 return;
570 spec->jack_present =
571 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
572 spec->autocfg.hp_pins);
573 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
581 if (!spec->automute || !spec->detect_line)
582 return;
583 spec->line_jack_present =
584 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
585 spec->autocfg.line_out_pins);
586 update_speakers(codec);
587}
588
Takashi Iwai8d087c72011-06-28 12:45:47 +0200589#define get_connection_index(codec, mux, nid) \
590 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200591
Takashi Iwai1d045db2011-07-07 18:23:21 +0200592/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200593static void alc_mic_automute(struct hda_codec *codec)
594{
595 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200596 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200597
Takashi Iwai21268962011-07-07 15:01:13 +0200598 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200599 return;
600 if (snd_BUG_ON(!spec->adc_nids))
601 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200602 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200603 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200604
Takashi Iwai21268962011-07-07 15:01:13 +0200605 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
606 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
607 else if (spec->dock_mic_idx >= 0 &&
608 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
609 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
610 else
611 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200612
Takashi Iwai21268962011-07-07 15:01:13 +0200613 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
614 if (spec->dock_mic_idx >= 0)
615 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200616}
617
Kailang Yangc9b58002007-10-16 14:30:01 +0200618/* unsolicited event for HP jack sensing */
619static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
620{
621 if (codec->vendor_id == 0x10ec0880)
622 res >>= 28;
623 else
624 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200625 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200626 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200627 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200628 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200629 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200630 alc_line_automute(codec);
631 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200632 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200633 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200634 break;
635 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200636}
637
Takashi Iwai1d045db2011-07-07 18:23:21 +0200638/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200639static void alc_inithook(struct hda_codec *codec)
640{
Takashi Iwaid922b512011-04-28 12:18:53 +0200641 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200642 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200643 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200644}
645
Kailang Yangf9423e72008-05-27 12:32:25 +0200646/* additional initialization for ALC888 variants */
647static void alc888_coef_init(struct hda_codec *codec)
648{
649 unsigned int tmp;
650
651 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
652 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
653 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100654 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200655 /* alc888S-VC */
656 snd_hda_codec_read(codec, 0x20, 0,
657 AC_VERB_SET_PROC_COEF, 0x830);
658 else
659 /* alc888-VB */
660 snd_hda_codec_read(codec, 0x20, 0,
661 AC_VERB_SET_PROC_COEF, 0x3030);
662}
663
Takashi Iwai1d045db2011-07-07 18:23:21 +0200664/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200665static void alc889_coef_init(struct hda_codec *codec)
666{
667 unsigned int tmp;
668
669 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
670 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
671 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
672 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
673}
674
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100675/* turn on/off EAPD control (only if available) */
676static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
677{
678 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
679 return;
680 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
681 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
682 on ? 2 : 0);
683}
684
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200685/* turn on/off EAPD controls of the codec */
686static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
687{
688 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200689 static hda_nid_t pins[] = {
690 0x0f, 0x10, 0x14, 0x15, 0
691 };
692 hda_nid_t *p;
693 for (p = pins; *p; p++)
694 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200695}
696
Takashi Iwai1c716152011-04-07 10:37:16 +0200697/* generic shutup callback;
698 * just turning off EPAD and a little pause for avoiding pop-noise
699 */
700static void alc_eapd_shutup(struct hda_codec *codec)
701{
702 alc_auto_setup_eapd(codec, false);
703 msleep(200);
704}
705
Takashi Iwai1d045db2011-07-07 18:23:21 +0200706/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200707static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200708{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200709 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200710
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200711 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200712 switch (type) {
713 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200714 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
715 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200716 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200717 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
718 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200719 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200720 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
721 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200722 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200723 switch (codec->vendor_id) {
724 case 0x10ec0260:
725 snd_hda_codec_write(codec, 0x1a, 0,
726 AC_VERB_SET_COEF_INDEX, 7);
727 tmp = snd_hda_codec_read(codec, 0x1a, 0,
728 AC_VERB_GET_PROC_COEF, 0);
729 snd_hda_codec_write(codec, 0x1a, 0,
730 AC_VERB_SET_COEF_INDEX, 7);
731 snd_hda_codec_write(codec, 0x1a, 0,
732 AC_VERB_SET_PROC_COEF,
733 tmp | 0x2010);
734 break;
735 case 0x10ec0262:
736 case 0x10ec0880:
737 case 0x10ec0882:
738 case 0x10ec0883:
739 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100740 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100741 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200742 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200743 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200744 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200745 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200746 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100747#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200748 case 0x10ec0267:
749 case 0x10ec0268:
750 snd_hda_codec_write(codec, 0x20, 0,
751 AC_VERB_SET_COEF_INDEX, 7);
752 tmp = snd_hda_codec_read(codec, 0x20, 0,
753 AC_VERB_GET_PROC_COEF, 0);
754 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200755 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200756 snd_hda_codec_write(codec, 0x20, 0,
757 AC_VERB_SET_PROC_COEF,
758 tmp | 0x3000);
759 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100760#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200761 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200762 break;
763 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200764}
Kailang Yangea1fb292008-08-26 12:58:38 +0200765
Takashi Iwai1d045db2011-07-07 18:23:21 +0200766/*
767 * Auto-Mute mode mixer enum support
768 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200769static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
770 struct snd_ctl_elem_info *uinfo)
771{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200772 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
773 struct alc_spec *spec = codec->spec;
774 static const char * const texts2[] = {
775 "Disabled", "Enabled"
776 };
777 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200778 "Disabled", "Speaker Only", "Line-Out+Speaker"
779 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200780 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200781
782 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
783 uinfo->count = 1;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200784 if (spec->automute_hp_lo) {
785 uinfo->value.enumerated.items = 3;
786 texts = texts3;
787 } else {
788 uinfo->value.enumerated.items = 2;
789 texts = texts2;
790 }
791 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
792 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200793 strcpy(uinfo->value.enumerated.name,
794 texts[uinfo->value.enumerated.item]);
795 return 0;
796}
797
798static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
799 struct snd_ctl_elem_value *ucontrol)
800{
801 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
802 struct alc_spec *spec = codec->spec;
803 unsigned int val;
804 if (!spec->automute)
805 val = 0;
806 else if (!spec->automute_lines)
807 val = 1;
808 else
809 val = 2;
810 ucontrol->value.enumerated.item[0] = val;
811 return 0;
812}
813
814static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
815 struct snd_ctl_elem_value *ucontrol)
816{
817 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
818 struct alc_spec *spec = codec->spec;
819
820 switch (ucontrol->value.enumerated.item[0]) {
821 case 0:
822 if (!spec->automute)
823 return 0;
824 spec->automute = 0;
825 break;
826 case 1:
827 if (spec->automute && !spec->automute_lines)
828 return 0;
829 spec->automute = 1;
830 spec->automute_lines = 0;
831 break;
832 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200833 if (!spec->automute_hp_lo)
834 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200835 if (spec->automute && spec->automute_lines)
836 return 0;
837 spec->automute = 1;
838 spec->automute_lines = 1;
839 break;
840 default:
841 return -EINVAL;
842 }
843 update_speakers(codec);
844 return 1;
845}
846
Takashi Iwaia9111322011-05-02 11:30:18 +0200847static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200848 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
849 .name = "Auto-Mute Mode",
850 .info = alc_automute_mode_info,
851 .get = alc_automute_mode_get,
852 .put = alc_automute_mode_put,
853};
854
Takashi Iwai1d045db2011-07-07 18:23:21 +0200855static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
856{
857 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
858 return snd_array_new(&spec->kctls);
859}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200860
861static int alc_add_automute_mode_enum(struct hda_codec *codec)
862{
863 struct alc_spec *spec = codec->spec;
864 struct snd_kcontrol_new *knew;
865
866 knew = alc_kcontrol_new(spec);
867 if (!knew)
868 return -ENOMEM;
869 *knew = alc_automute_mode_enum;
870 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
871 if (!knew->name)
872 return -ENOMEM;
873 return 0;
874}
875
Takashi Iwai1d045db2011-07-07 18:23:21 +0200876/*
877 * Check the availability of HP/line-out auto-mute;
878 * Set up appropriately if really supported
879 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200880static void alc_init_auto_hp(struct hda_codec *codec)
881{
882 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200883 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200884 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200885 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200886
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200887 if (cfg->hp_pins[0])
888 present++;
889 if (cfg->line_out_pins[0])
890 present++;
891 if (cfg->speaker_pins[0])
892 present++;
893 if (present < 2) /* need two different output types */
894 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200895 if (present == 3)
896 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200897
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200898 if (!cfg->speaker_pins[0] &&
899 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200900 memcpy(cfg->speaker_pins, cfg->line_out_pins,
901 sizeof(cfg->speaker_pins));
902 cfg->speaker_outs = cfg->line_outs;
903 }
904
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200905 if (!cfg->hp_pins[0] &&
906 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200907 memcpy(cfg->hp_pins, cfg->line_out_pins,
908 sizeof(cfg->hp_pins));
909 cfg->hp_outs = cfg->line_outs;
910 }
911
912 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200913 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200914 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200915 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200916 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200917 nid);
918 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200919 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200920 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200921 spec->automute = 1;
922 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200923 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200924 if (spec->automute && cfg->line_out_pins[0] &&
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200925 cfg->speaker_pins[0] &&
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200926 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
927 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
928 for (i = 0; i < cfg->line_outs; i++) {
929 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200930 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200931 continue;
932 snd_printdd("realtek: Enable Line-Out auto-muting "
933 "on NID 0x%x\n", nid);
934 snd_hda_codec_write_cache(codec, nid, 0,
935 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200936 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200937 spec->detect_line = 1;
938 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200939 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200940 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200941
942 if (spec->automute) {
943 /* create a control for automute mode */
944 alc_add_automute_mode_enum(codec);
945 spec->unsol_event = alc_sku_unsol_event;
946 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200947}
948
Takashi Iwai1d045db2011-07-07 18:23:21 +0200949/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200950static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
951{
952 int i;
953 for (i = 0; i < nums; i++)
954 if (list[i] == nid)
955 return i;
956 return -1;
957}
958
Takashi Iwai1d045db2011-07-07 18:23:21 +0200959/* check whether dynamic ADC-switching is available */
960static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
961{
962 struct alc_spec *spec = codec->spec;
963 struct hda_input_mux *imux = &spec->private_imux[0];
964 int i, n, idx;
965 hda_nid_t cap, pin;
966
967 if (imux != spec->input_mux) /* no dynamic imux? */
968 return false;
969
970 for (n = 0; n < spec->num_adc_nids; n++) {
971 cap = spec->private_capsrc_nids[n];
972 for (i = 0; i < imux->num_items; i++) {
973 pin = spec->imux_pins[i];
974 if (!pin)
975 return false;
976 if (get_connection_index(codec, cap, pin) < 0)
977 break;
978 }
979 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +0200980 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +0200981 }
982
983 for (i = 0; i < imux->num_items; i++) {
984 pin = spec->imux_pins[i];
985 for (n = 0; n < spec->num_adc_nids; n++) {
986 cap = spec->private_capsrc_nids[n];
987 idx = get_connection_index(codec, cap, pin);
988 if (idx >= 0) {
989 imux->items[i].index = idx;
990 spec->dyn_adc_idx[i] = n;
991 break;
992 }
993 }
994 }
995
996 snd_printdd("realtek: enabling ADC switching\n");
997 spec->dyn_adc_switch = 1;
998 return true;
999}
Takashi Iwai21268962011-07-07 15:01:13 +02001000
1001/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1002static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1003{
1004 struct alc_spec *spec = codec->spec;
1005 struct hda_input_mux *imux;
1006 static char * const texts[3] = {
1007 "Mic", "Internal Mic", "Dock Mic"
1008 };
1009 int i;
1010
1011 if (!spec->auto_mic)
1012 return false;
1013 imux = &spec->private_imux[0];
1014 if (spec->input_mux == imux)
1015 return true;
1016 spec->imux_pins[0] = spec->ext_mic_pin;
1017 spec->imux_pins[1] = spec->int_mic_pin;
1018 spec->imux_pins[2] = spec->dock_mic_pin;
1019 for (i = 0; i < 3; i++) {
1020 strcpy(imux->items[i].label, texts[i]);
1021 if (spec->imux_pins[i])
1022 imux->num_items = i + 1;
1023 }
1024 spec->num_mux_defs = 1;
1025 spec->input_mux = imux;
1026 return true;
1027}
1028
1029/* check whether all auto-mic pins are valid; setup indices if OK */
1030static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1031{
1032 struct alc_spec *spec = codec->spec;
1033 const struct hda_input_mux *imux;
1034
1035 if (!spec->auto_mic)
1036 return false;
1037 if (spec->auto_mic_valid_imux)
1038 return true; /* already checked */
1039
1040 /* fill up imux indices */
1041 if (!alc_check_dyn_adc_switch(codec)) {
1042 spec->auto_mic = 0;
1043 return false;
1044 }
1045
1046 imux = spec->input_mux;
1047 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1048 spec->imux_pins, imux->num_items);
1049 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1050 spec->imux_pins, imux->num_items);
1051 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1052 spec->imux_pins, imux->num_items);
1053 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1054 spec->auto_mic = 0;
1055 return false; /* no corresponding imux */
1056 }
1057
1058 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1059 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001060 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001061 if (spec->dock_mic_pin)
1062 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1063 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001064 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001065
1066 spec->auto_mic_valid_imux = 1;
1067 spec->auto_mic = 1;
1068 return true;
1069}
1070
Takashi Iwai1d045db2011-07-07 18:23:21 +02001071/*
1072 * Check the availability of auto-mic switch;
1073 * Set up if really supported
1074 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001075static void alc_init_auto_mic(struct hda_codec *codec)
1076{
1077 struct alc_spec *spec = codec->spec;
1078 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001079 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001080 int i;
1081
Takashi Iwai21268962011-07-07 15:01:13 +02001082 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1083
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001084 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001085 for (i = 0; i < cfg->num_inputs; i++) {
1086 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001087 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001088 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001089 switch (snd_hda_get_input_pin_attr(defcfg)) {
1090 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001091 if (fixed)
1092 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001093 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1094 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001095 fixed = nid;
1096 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001097 case INPUT_PIN_ATTR_UNUSED:
1098 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001099 case INPUT_PIN_ATTR_DOCK:
1100 if (dock)
1101 return; /* already occupied */
1102 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1103 return; /* invalid type */
1104 dock = nid;
1105 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001106 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001107 if (ext)
1108 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001109 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1110 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001111 ext = nid;
1112 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001113 }
1114 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001115 if (!ext && dock) {
1116 ext = dock;
1117 dock = 0;
1118 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001119 if (!ext || !fixed)
1120 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001121 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001122 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001123 if (dock && !is_jack_detectable(codec, dock))
1124 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001125
1126 /* check imux indices */
1127 spec->ext_mic_pin = ext;
1128 spec->int_mic_pin = fixed;
1129 spec->dock_mic_pin = dock;
1130
1131 spec->auto_mic = 1;
1132 if (!alc_auto_mic_check_imux(codec))
1133 return;
1134
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001135 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1136 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001137 spec->unsol_event = alc_sku_unsol_event;
1138}
1139
Takashi Iwai1d045db2011-07-07 18:23:21 +02001140/* check the availabilities of auto-mute and auto-mic switches */
1141static void alc_auto_check_switches(struct hda_codec *codec)
1142{
1143 alc_init_auto_hp(codec);
1144 alc_init_auto_mic(codec);
1145}
1146
1147/*
1148 * Realtek SSID verification
1149 */
1150
David Henningsson90622912010-10-14 14:50:18 +02001151/* Could be any non-zero and even value. When used as fixup, tells
1152 * the driver to ignore any present sku defines.
1153 */
1154#define ALC_FIXUP_SKU_IGNORE (2)
1155
Kailang Yangda00c242010-03-19 11:23:45 +01001156static int alc_auto_parse_customize_define(struct hda_codec *codec)
1157{
1158 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001159 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001160 struct alc_spec *spec = codec->spec;
1161
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001162 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1163
David Henningsson90622912010-10-14 14:50:18 +02001164 if (spec->cdefine.fixup) {
1165 ass = spec->cdefine.sku_cfg;
1166 if (ass == ALC_FIXUP_SKU_IGNORE)
1167 return -1;
1168 goto do_sku;
1169 }
1170
Kailang Yangda00c242010-03-19 11:23:45 +01001171 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001172 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001173 goto do_sku;
1174
1175 nid = 0x1d;
1176 if (codec->vendor_id == 0x10ec0260)
1177 nid = 0x17;
1178 ass = snd_hda_codec_get_pincfg(codec, nid);
1179
1180 if (!(ass & 1)) {
1181 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1182 codec->chip_name, ass);
1183 return -1;
1184 }
1185
1186 /* check sum */
1187 tmp = 0;
1188 for (i = 1; i < 16; i++) {
1189 if ((ass >> i) & 1)
1190 tmp++;
1191 }
1192 if (((ass >> 16) & 0xf) != tmp)
1193 return -1;
1194
1195 spec->cdefine.port_connectivity = ass >> 30;
1196 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1197 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1198 spec->cdefine.customization = ass >> 8;
1199do_sku:
1200 spec->cdefine.sku_cfg = ass;
1201 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1202 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1203 spec->cdefine.swap = (ass & 0x2) >> 1;
1204 spec->cdefine.override = ass & 0x1;
1205
1206 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1207 nid, spec->cdefine.sku_cfg);
1208 snd_printd("SKU: port_connectivity=0x%x\n",
1209 spec->cdefine.port_connectivity);
1210 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1211 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1212 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1213 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1214 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1215 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1216 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1217
1218 return 0;
1219}
1220
Takashi Iwai1d045db2011-07-07 18:23:21 +02001221/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001222static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1223{
Takashi Iwai21268962011-07-07 15:01:13 +02001224 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001225}
1226
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001227/* check subsystem ID and set up device-specific initialization;
1228 * return 1 if initialized, 0 if invalid SSID
1229 */
1230/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1231 * 31 ~ 16 : Manufacture ID
1232 * 15 ~ 8 : SKU ID
1233 * 7 ~ 0 : Assembly ID
1234 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1235 */
1236static int alc_subsystem_id(struct hda_codec *codec,
1237 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001238 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001239{
1240 unsigned int ass, tmp, i;
1241 unsigned nid;
1242 struct alc_spec *spec = codec->spec;
1243
David Henningsson90622912010-10-14 14:50:18 +02001244 if (spec->cdefine.fixup) {
1245 ass = spec->cdefine.sku_cfg;
1246 if (ass == ALC_FIXUP_SKU_IGNORE)
1247 return 0;
1248 goto do_sku;
1249 }
1250
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001251 ass = codec->subsystem_id & 0xffff;
1252 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1253 goto do_sku;
1254
1255 /* invalid SSID, check the special NID pin defcfg instead */
1256 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001257 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001258 * 29~21 : reserve
1259 * 20 : PCBEEP input
1260 * 19~16 : Check sum (15:1)
1261 * 15~1 : Custom
1262 * 0 : override
1263 */
1264 nid = 0x1d;
1265 if (codec->vendor_id == 0x10ec0260)
1266 nid = 0x17;
1267 ass = snd_hda_codec_get_pincfg(codec, nid);
1268 snd_printd("realtek: No valid SSID, "
1269 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001270 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001271 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001272 return 0;
1273 if ((ass >> 30) != 1) /* no physical connection */
1274 return 0;
1275
1276 /* check sum */
1277 tmp = 0;
1278 for (i = 1; i < 16; i++) {
1279 if ((ass >> i) & 1)
1280 tmp++;
1281 }
1282 if (((ass >> 16) & 0xf) != tmp)
1283 return 0;
1284do_sku:
1285 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1286 ass & 0xffff, codec->vendor_id);
1287 /*
1288 * 0 : override
1289 * 1 : Swap Jack
1290 * 2 : 0 --> Desktop, 1 --> Laptop
1291 * 3~5 : External Amplifier control
1292 * 7~6 : Reserved
1293 */
1294 tmp = (ass & 0x38) >> 3; /* external Amp control */
1295 switch (tmp) {
1296 case 1:
1297 spec->init_amp = ALC_INIT_GPIO1;
1298 break;
1299 case 3:
1300 spec->init_amp = ALC_INIT_GPIO2;
1301 break;
1302 case 7:
1303 spec->init_amp = ALC_INIT_GPIO3;
1304 break;
1305 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001306 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001307 spec->init_amp = ALC_INIT_DEFAULT;
1308 break;
1309 }
1310
1311 /* is laptop or Desktop and enable the function "Mute internal speaker
1312 * when the external headphone out jack is plugged"
1313 */
1314 if (!(ass & 0x8000))
1315 return 1;
1316 /*
1317 * 10~8 : Jack location
1318 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1319 * 14~13: Resvered
1320 * 15 : 1 --> enable the function "Mute internal speaker
1321 * when the external headphone out jack is plugged"
1322 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001323 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001324 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001325 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1326 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001327 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001328 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001329 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001330 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001331 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001332 else if (tmp == 3)
1333 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001334 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001335 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001336 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1337 spec->autocfg.line_outs))
1338 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001339 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001340 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001341 return 1;
1342}
Kailang Yangea1fb292008-08-26 12:58:38 +02001343
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001344/* Check the validity of ALC subsystem-id
1345 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1346static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001347{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001348 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001349 struct alc_spec *spec = codec->spec;
1350 snd_printd("realtek: "
1351 "Enable default setup for auto mode as fallback\n");
1352 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001353 }
Takashi Iwai21268962011-07-07 15:01:13 +02001354}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001355
Takashi Iwai41e41f12005-06-08 14:48:49 +02001356/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001357 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001358 */
1359
1360struct alc_pincfg {
1361 hda_nid_t nid;
1362 u32 val;
1363};
1364
Todd Broche1eb5f12010-12-06 11:19:51 -08001365struct alc_model_fixup {
1366 const int id;
1367 const char *name;
1368};
1369
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001370struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001371 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001372 bool chained;
1373 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001374 union {
1375 unsigned int sku;
1376 const struct alc_pincfg *pins;
1377 const struct hda_verb *verbs;
1378 void (*func)(struct hda_codec *codec,
1379 const struct alc_fixup *fix,
1380 int action);
1381 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001382};
1383
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001384enum {
1385 ALC_FIXUP_INVALID,
1386 ALC_FIXUP_SKU,
1387 ALC_FIXUP_PINS,
1388 ALC_FIXUP_VERBS,
1389 ALC_FIXUP_FUNC,
1390};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001391
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001392enum {
1393 ALC_FIXUP_ACT_PRE_PROBE,
1394 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001395 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001396};
1397
1398static void alc_apply_fixup(struct hda_codec *codec, int action)
1399{
1400 struct alc_spec *spec = codec->spec;
1401 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001402#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001403 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001404#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001405 int depth = 0;
1406
1407 if (!spec->fixup_list)
1408 return;
1409
1410 while (id >= 0) {
1411 const struct alc_fixup *fix = spec->fixup_list + id;
1412 const struct alc_pincfg *cfg;
1413
1414 switch (fix->type) {
1415 case ALC_FIXUP_SKU:
1416 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1417 break;;
1418 snd_printdd(KERN_INFO "hda_codec: %s: "
1419 "Apply sku override for %s\n",
1420 codec->chip_name, modelname);
1421 spec->cdefine.sku_cfg = fix->v.sku;
1422 spec->cdefine.fixup = 1;
1423 break;
1424 case ALC_FIXUP_PINS:
1425 cfg = fix->v.pins;
1426 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1427 break;
1428 snd_printdd(KERN_INFO "hda_codec: %s: "
1429 "Apply pincfg for %s\n",
1430 codec->chip_name, modelname);
1431 for (; cfg->nid; cfg++)
1432 snd_hda_codec_set_pincfg(codec, cfg->nid,
1433 cfg->val);
1434 break;
1435 case ALC_FIXUP_VERBS:
1436 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1437 break;
1438 snd_printdd(KERN_INFO "hda_codec: %s: "
1439 "Apply fix-verbs for %s\n",
1440 codec->chip_name, modelname);
1441 add_verb(codec->spec, fix->v.verbs);
1442 break;
1443 case ALC_FIXUP_FUNC:
1444 if (!fix->v.func)
1445 break;
1446 snd_printdd(KERN_INFO "hda_codec: %s: "
1447 "Apply fix-func for %s\n",
1448 codec->chip_name, modelname);
1449 fix->v.func(codec, fix, action);
1450 break;
1451 default:
1452 snd_printk(KERN_ERR "hda_codec: %s: "
1453 "Invalid fixup type %d\n",
1454 codec->chip_name, fix->type);
1455 break;
1456 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001457 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001458 break;
1459 if (++depth > 10)
1460 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001461 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001462 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001463}
1464
Todd Broche1eb5f12010-12-06 11:19:51 -08001465static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001466 const struct alc_model_fixup *models,
1467 const struct snd_pci_quirk *quirk,
1468 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001469{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001470 struct alc_spec *spec = codec->spec;
1471 int id = -1;
1472 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001473
Todd Broche1eb5f12010-12-06 11:19:51 -08001474 if (codec->modelname && models) {
1475 while (models->name) {
1476 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001477 id = models->id;
1478 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001479 break;
1480 }
1481 models++;
1482 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001483 }
1484 if (id < 0) {
1485 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1486 if (quirk) {
1487 id = quirk->value;
1488#ifdef CONFIG_SND_DEBUG_VERBOSE
1489 name = quirk->name;
1490#endif
1491 }
1492 }
1493
1494 spec->fixup_id = id;
1495 if (id >= 0) {
1496 spec->fixup_list = fixlist;
1497 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001498 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001499}
1500
Takashi Iwai1d045db2011-07-07 18:23:21 +02001501/*
1502 * COEF access helper functions
1503 */
Kailang Yang274693f2009-12-03 10:07:50 +01001504static int alc_read_coef_idx(struct hda_codec *codec,
1505 unsigned int coef_idx)
1506{
1507 unsigned int val;
1508 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1509 coef_idx);
1510 val = snd_hda_codec_read(codec, 0x20, 0,
1511 AC_VERB_GET_PROC_COEF, 0);
1512 return val;
1513}
1514
Kailang Yang977ddd62010-09-15 10:02:29 +02001515static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1516 unsigned int coef_val)
1517{
1518 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1519 coef_idx);
1520 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1521 coef_val);
1522}
1523
Takashi Iwai1d045db2011-07-07 18:23:21 +02001524/*
1525 * Digital I/O handling
1526 */
1527
Takashi Iwai757899a2010-07-30 10:48:14 +02001528/* set right pin controls for digital I/O */
1529static void alc_auto_init_digital(struct hda_codec *codec)
1530{
1531 struct alc_spec *spec = codec->spec;
1532 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001533 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001534
1535 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1536 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001537 if (!pin)
1538 continue;
1539 snd_hda_codec_write(codec, pin, 0,
1540 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1541 if (!i)
1542 dac = spec->multiout.dig_out_nid;
1543 else
1544 dac = spec->slave_dig_outs[i - 1];
1545 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1546 continue;
1547 snd_hda_codec_write(codec, dac, 0,
1548 AC_VERB_SET_AMP_GAIN_MUTE,
1549 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001550 }
1551 pin = spec->autocfg.dig_in_pin;
1552 if (pin)
1553 snd_hda_codec_write(codec, pin, 0,
1554 AC_VERB_SET_PIN_WIDGET_CONTROL,
1555 PIN_IN);
1556}
1557
1558/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1559static void alc_auto_parse_digital(struct hda_codec *codec)
1560{
1561 struct alc_spec *spec = codec->spec;
1562 int i, err;
1563 hda_nid_t dig_nid;
1564
1565 /* support multiple SPDIFs; the secondary is set up as a slave */
1566 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001567 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001568 err = snd_hda_get_connections(codec,
1569 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001570 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001571 if (err < 0)
1572 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001573 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001574 if (!i) {
1575 spec->multiout.dig_out_nid = dig_nid;
1576 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1577 } else {
1578 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1579 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1580 break;
1581 spec->slave_dig_outs[i - 1] = dig_nid;
1582 }
1583 }
1584
1585 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001586 dig_nid = codec->start_nid;
1587 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1588 unsigned int wcaps = get_wcaps(codec, dig_nid);
1589 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1590 continue;
1591 if (!(wcaps & AC_WCAP_DIGITAL))
1592 continue;
1593 if (!(wcaps & AC_WCAP_CONN_LIST))
1594 continue;
1595 err = get_connection_index(codec, dig_nid,
1596 spec->autocfg.dig_in_pin);
1597 if (err >= 0) {
1598 spec->dig_in_nid = dig_nid;
1599 break;
1600 }
1601 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001602 }
1603}
1604
Takashi Iwaif95474e2007-07-10 00:47:43 +02001605/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001606 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001607 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001608static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1609 struct snd_ctl_elem_info *uinfo)
1610{
1611 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1612 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001613 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001614 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001615
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001616 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001617 if (spec->vol_in_capsrc)
1618 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1619 else
1620 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1621 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001622 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001623 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001624 return err;
1625}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001627static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1628 unsigned int size, unsigned int __user *tlv)
1629{
1630 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1631 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001632 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001633 int err;
1634
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001635 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001636 if (spec->vol_in_capsrc)
1637 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1638 else
1639 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1640 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001641 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001642 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001643 return err;
1644}
1645
1646typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1647 struct snd_ctl_elem_value *ucontrol);
1648
1649static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1650 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001651 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001652{
1653 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1654 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001655 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001656
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001657 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001658 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001659 for (i = 0; i < spec->num_adc_nids; i++) {
1660 kcontrol->private_value =
1661 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1662 3, 0, HDA_INPUT);
1663 err = func(kcontrol, ucontrol);
1664 if (err < 0)
1665 goto error;
1666 }
1667 } else {
1668 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001669 if (spec->vol_in_capsrc)
1670 kcontrol->private_value =
1671 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1672 3, 0, HDA_OUTPUT);
1673 else
1674 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001675 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1676 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001677 err = func(kcontrol, ucontrol);
1678 }
1679 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001680 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001681 return err;
1682}
1683
1684static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1685 struct snd_ctl_elem_value *ucontrol)
1686{
1687 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001688 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001689}
1690
1691static int alc_cap_vol_put(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_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001696}
1697
1698/* capture mixer elements */
1699#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1700
1701static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1702 struct snd_ctl_elem_value *ucontrol)
1703{
1704 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001705 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001706}
1707
1708static int alc_cap_sw_put(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_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001713}
1714
Takashi Iwaia23b6882009-03-23 15:21:36 +01001715#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001716 { \
1717 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1718 .name = "Capture Switch", \
1719 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1720 .count = num, \
1721 .info = alc_cap_sw_info, \
1722 .get = alc_cap_sw_get, \
1723 .put = alc_cap_sw_put, \
1724 }, \
1725 { \
1726 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1727 .name = "Capture Volume", \
1728 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1729 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1730 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1731 .count = num, \
1732 .info = alc_cap_vol_info, \
1733 .get = alc_cap_vol_get, \
1734 .put = alc_cap_vol_put, \
1735 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001736 }
1737
1738#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001739 { \
1740 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1741 /* .name = "Capture Source", */ \
1742 .name = "Input Source", \
1743 .count = num, \
1744 .info = alc_mux_enum_info, \
1745 .get = alc_mux_enum_get, \
1746 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001747 }
1748
1749#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001750static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001751 _DEFINE_CAPMIX(num), \
1752 _DEFINE_CAPSRC(num), \
1753 { } /* end */ \
1754}
1755
1756#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001757static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001758 _DEFINE_CAPMIX(num), \
1759 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001760}
1761
1762/* up to three ADCs */
1763DEFINE_CAPMIX(1);
1764DEFINE_CAPMIX(2);
1765DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001766DEFINE_CAPMIX_NOSRC(1);
1767DEFINE_CAPMIX_NOSRC(2);
1768DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001769
1770/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001771 * virtual master controls
1772 */
1773
1774/*
1775 * slave controls for virtual master
1776 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001777static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001778 "Front Playback Volume",
1779 "Surround Playback Volume",
1780 "Center Playback Volume",
1781 "LFE Playback Volume",
1782 "Side Playback Volume",
1783 "Headphone Playback Volume",
1784 "Speaker Playback Volume",
1785 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001786 "Line-Out Playback Volume",
1787 NULL,
1788};
1789
Takashi Iwaiea734962011-01-17 11:29:34 +01001790static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001791 "Front Playback Switch",
1792 "Surround Playback Switch",
1793 "Center Playback Switch",
1794 "LFE Playback Switch",
1795 "Side Playback Switch",
1796 "Headphone Playback Switch",
1797 "Speaker Playback Switch",
1798 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001799 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001800 "Line-Out Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001801 NULL,
1802};
1803
1804/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001805 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001807
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001808#define NID_MAPPING (-1)
1809
1810#define SUBDEV_SPEAKER_ (0 << 6)
1811#define SUBDEV_HP_ (1 << 6)
1812#define SUBDEV_LINE_ (2 << 6)
1813#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1814#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1815#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1816
Takashi Iwai603c4012008-07-30 15:01:44 +02001817static void alc_free_kctls(struct hda_codec *codec);
1818
Takashi Iwai67d634c2009-11-16 15:35:59 +01001819#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001820/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001821static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001822 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001823 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001824 { } /* end */
1825};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001826#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001827
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828static int alc_build_controls(struct hda_codec *codec)
1829{
1830 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001831 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001832 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001833 int i, j, err;
1834 unsigned int u;
1835 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
1837 for (i = 0; i < spec->num_mixers; i++) {
1838 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1839 if (err < 0)
1840 return err;
1841 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001842 if (spec->cap_mixer) {
1843 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1844 if (err < 0)
1845 return err;
1846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001848 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001849 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001850 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 if (err < 0)
1852 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001853 if (!spec->no_analog) {
1854 err = snd_hda_create_spdif_share_sw(codec,
1855 &spec->multiout);
1856 if (err < 0)
1857 return err;
1858 spec->multiout.share_spdif = 1;
1859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 }
1861 if (spec->dig_in_nid) {
1862 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1863 if (err < 0)
1864 return err;
1865 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001866
Takashi Iwai67d634c2009-11-16 15:35:59 +01001867#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001868 /* create beep controls if needed */
1869 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001870 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001871 for (knew = alc_beep_mixer; knew->name; knew++) {
1872 struct snd_kcontrol *kctl;
1873 kctl = snd_ctl_new1(knew, codec);
1874 if (!kctl)
1875 return -ENOMEM;
1876 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001877 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001878 if (err < 0)
1879 return err;
1880 }
1881 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001882#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001883
Takashi Iwai2134ea42008-01-10 16:53:55 +01001884 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001885 if (!spec->no_analog &&
1886 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001887 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001888 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001889 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001890 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001891 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001892 if (err < 0)
1893 return err;
1894 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001895 if (!spec->no_analog &&
1896 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001897 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1898 NULL, alc_slave_sws);
1899 if (err < 0)
1900 return err;
1901 }
1902
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001903 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001904 if (spec->capsrc_nids || spec->adc_nids) {
1905 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1906 if (!kctl)
1907 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1908 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001909 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001910 if (!nids)
1911 nids = spec->adc_nids;
1912 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1913 if (err < 0)
1914 return err;
1915 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001916 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001917 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001918 const char *kname = kctl ? kctl->id.name : NULL;
1919 for (knew = spec->cap_mixer; knew->name; knew++) {
1920 if (kname && strcmp(knew->name, kname) == 0)
1921 continue;
1922 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1923 for (i = 0; kctl && i < kctl->count; i++) {
1924 err = snd_hda_add_nid(codec, kctl, i,
1925 spec->adc_nids[i]);
1926 if (err < 0)
1927 return err;
1928 }
1929 }
1930 }
1931
1932 /* other nid->control mapping */
1933 for (i = 0; i < spec->num_mixers; i++) {
1934 for (knew = spec->mixers[i]; knew->name; knew++) {
1935 if (knew->iface != NID_MAPPING)
1936 continue;
1937 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1938 if (kctl == NULL)
1939 continue;
1940 u = knew->subdevice;
1941 for (j = 0; j < 4; j++, u >>= 8) {
1942 nid = u & 0x3f;
1943 if (nid == 0)
1944 continue;
1945 switch (u & 0xc0) {
1946 case SUBDEV_SPEAKER_:
1947 nid = spec->autocfg.speaker_pins[nid];
1948 break;
1949 case SUBDEV_LINE_:
1950 nid = spec->autocfg.line_out_pins[nid];
1951 break;
1952 case SUBDEV_HP_:
1953 nid = spec->autocfg.hp_pins[nid];
1954 break;
1955 default:
1956 continue;
1957 }
1958 err = snd_hda_add_nid(codec, kctl, 0, nid);
1959 if (err < 0)
1960 return err;
1961 }
1962 u = knew->private_value;
1963 for (j = 0; j < 4; j++, u >>= 8) {
1964 nid = u & 0xff;
1965 if (nid == 0)
1966 continue;
1967 err = snd_hda_add_nid(codec, kctl, 0, nid);
1968 if (err < 0)
1969 return err;
1970 }
1971 }
1972 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001973
1974 alc_free_kctls(codec); /* no longer needed */
1975
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 return 0;
1977}
1978
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001979
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001981 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001982 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001983
Takashi Iwai584c0c42011-03-10 12:51:11 +01001984static void alc_init_special_input_src(struct hda_codec *codec);
1985
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986static int alc_init(struct hda_codec *codec)
1987{
1988 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001989 unsigned int i;
1990
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001991 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001992 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001993
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001994 for (i = 0; i < spec->num_init_verbs; i++)
1995 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01001996 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001997
1998 if (spec->init_hook)
1999 spec->init_hook(codec);
2000
Takashi Iwai58701122011-01-13 15:41:45 +01002001 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2002
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002003 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 return 0;
2005}
2006
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002007static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2008{
2009 struct alc_spec *spec = codec->spec;
2010
2011 if (spec->unsol_event)
2012 spec->unsol_event(codec, res);
2013}
2014
Takashi Iwaicb53c622007-08-10 17:21:45 +02002015#ifdef CONFIG_SND_HDA_POWER_SAVE
2016static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2017{
2018 struct alc_spec *spec = codec->spec;
2019 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2020}
2021#endif
2022
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023/*
2024 * Analog playback callbacks
2025 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002026static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002028 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029{
2030 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002031 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2032 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033}
2034
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002035static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 struct hda_codec *codec,
2037 unsigned int stream_tag,
2038 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002039 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040{
2041 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002042 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2043 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044}
2045
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002046static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 struct hda_codec *codec,
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;
2051 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2052}
2053
2054/*
2055 * Digital out
2056 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002057static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002059 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060{
2061 struct alc_spec *spec = codec->spec;
2062 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2063}
2064
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002065static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002066 struct hda_codec *codec,
2067 unsigned int stream_tag,
2068 unsigned int format,
2069 struct snd_pcm_substream *substream)
2070{
2071 struct alc_spec *spec = codec->spec;
2072 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2073 stream_tag, format, substream);
2074}
2075
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002076static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002077 struct hda_codec *codec,
2078 struct snd_pcm_substream *substream)
2079{
2080 struct alc_spec *spec = codec->spec;
2081 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2082}
2083
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002084static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002086 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087{
2088 struct alc_spec *spec = codec->spec;
2089 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2090}
2091
2092/*
2093 * Analog capture
2094 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002095static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 struct hda_codec *codec,
2097 unsigned int stream_tag,
2098 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002099 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100{
2101 struct alc_spec *spec = codec->spec;
2102
Takashi Iwai63300792008-01-24 15:31:36 +01002103 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 stream_tag, 0, format);
2105 return 0;
2106}
2107
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002108static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002110 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111{
2112 struct alc_spec *spec = codec->spec;
2113
Takashi Iwai888afa12008-03-18 09:57:50 +01002114 snd_hda_codec_cleanup_stream(codec,
2115 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 return 0;
2117}
2118
Takashi Iwai840b64c2010-07-13 22:49:01 +02002119/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002120static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002121 struct hda_codec *codec,
2122 unsigned int stream_tag,
2123 unsigned int format,
2124 struct snd_pcm_substream *substream)
2125{
2126 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002127 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002128 spec->cur_adc_stream_tag = stream_tag;
2129 spec->cur_adc_format = format;
2130 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2131 return 0;
2132}
2133
Takashi Iwai21268962011-07-07 15:01:13 +02002134static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002135 struct hda_codec *codec,
2136 struct snd_pcm_substream *substream)
2137{
2138 struct alc_spec *spec = codec->spec;
2139 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2140 spec->cur_adc = 0;
2141 return 0;
2142}
2143
Takashi Iwai21268962011-07-07 15:01:13 +02002144static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002145 .substreams = 1,
2146 .channels_min = 2,
2147 .channels_max = 2,
2148 .nid = 0, /* fill later */
2149 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002150 .prepare = dyn_adc_capture_pcm_prepare,
2151 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002152 },
2153};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154
2155/*
2156 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002157static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 .substreams = 1,
2159 .channels_min = 2,
2160 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002161 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002163 .open = alc_playback_pcm_open,
2164 .prepare = alc_playback_pcm_prepare,
2165 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 },
2167};
2168
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002169static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002170 .substreams = 1,
2171 .channels_min = 2,
2172 .channels_max = 2,
2173 /* NID is set in alc_build_pcms */
2174};
2175
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002176static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002177 .substreams = 1,
2178 .channels_min = 2,
2179 .channels_max = 2,
2180 /* NID is set in alc_build_pcms */
2181};
2182
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002183static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002184 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 .channels_min = 2,
2186 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002187 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002189 .prepare = alc_alt_capture_pcm_prepare,
2190 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 },
2192};
2193
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002194static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 .substreams = 1,
2196 .channels_min = 2,
2197 .channels_max = 2,
2198 /* NID is set in alc_build_pcms */
2199 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002200 .open = alc_dig_playback_pcm_open,
2201 .close = alc_dig_playback_pcm_close,
2202 .prepare = alc_dig_playback_pcm_prepare,
2203 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 },
2205};
2206
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002207static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 .substreams = 1,
2209 .channels_min = 2,
2210 .channels_max = 2,
2211 /* NID is set in alc_build_pcms */
2212};
2213
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002214/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002215static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002216 .substreams = 0,
2217 .channels_min = 0,
2218 .channels_max = 0,
2219};
2220
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221static int alc_build_pcms(struct hda_codec *codec)
2222{
2223 struct alc_spec *spec = codec->spec;
2224 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002225 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 int i;
2227
2228 codec->num_pcms = 1;
2229 codec->pcm_info = info;
2230
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002231 if (spec->no_analog)
2232 goto skip_analog;
2233
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002234 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2235 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002237
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002238 if (spec->multiout.dac_nids > 0) {
2239 p = spec->stream_analog_playback;
2240 if (!p)
2241 p = &alc_pcm_analog_playback;
2242 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002243 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2244 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002245 if (spec->adc_nids) {
2246 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002247 if (!p) {
2248 if (spec->dyn_adc_switch)
2249 p = &dyn_adc_pcm_analog_capture;
2250 else
2251 p = &alc_pcm_analog_capture;
2252 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002253 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002254 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256
Takashi Iwai4a471b72005-12-07 13:56:29 +01002257 if (spec->channel_mode) {
2258 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2259 for (i = 0; i < spec->num_channel_mode; i++) {
2260 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2261 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 }
2264 }
2265
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002266 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002267 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002269 snprintf(spec->stream_name_digital,
2270 sizeof(spec->stream_name_digital),
2271 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002272 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002273 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002274 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002276 if (spec->dig_out_type)
2277 info->pcm_type = spec->dig_out_type;
2278 else
2279 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002280 if (spec->multiout.dig_out_nid) {
2281 p = spec->stream_digital_playback;
2282 if (!p)
2283 p = &alc_pcm_digital_playback;
2284 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2286 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002287 if (spec->dig_in_nid) {
2288 p = spec->stream_digital_capture;
2289 if (!p)
2290 p = &alc_pcm_digital_capture;
2291 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2293 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002294 /* FIXME: do we need this for all Realtek codec models? */
2295 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 }
2297
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002298 if (spec->no_analog)
2299 return 0;
2300
Takashi Iwaie08a0072006-09-07 17:52:14 +02002301 /* If the use of more than one ADC is requested for the current
2302 * model, configure a second analog capture-only PCM.
2303 */
2304 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002305 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002306 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002307 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002308 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002309 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002310 p = spec->stream_analog_alt_playback;
2311 if (!p)
2312 p = &alc_pcm_analog_alt_playback;
2313 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002314 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2315 spec->alt_dac_nid;
2316 } else {
2317 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2318 alc_pcm_null_stream;
2319 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2320 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002321 if (spec->num_adc_nids > 1) {
2322 p = spec->stream_analog_alt_capture;
2323 if (!p)
2324 p = &alc_pcm_analog_alt_capture;
2325 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002326 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2327 spec->adc_nids[1];
2328 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2329 spec->num_adc_nids - 1;
2330 } else {
2331 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2332 alc_pcm_null_stream;
2333 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002334 }
2335 }
2336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 return 0;
2338}
2339
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002340static inline void alc_shutup(struct hda_codec *codec)
2341{
Takashi Iwai1c716152011-04-07 10:37:16 +02002342 struct alc_spec *spec = codec->spec;
2343
2344 if (spec && spec->shutup)
2345 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002346 snd_hda_shutup_pins(codec);
2347}
2348
Takashi Iwai603c4012008-07-30 15:01:44 +02002349static void alc_free_kctls(struct hda_codec *codec)
2350{
2351 struct alc_spec *spec = codec->spec;
2352
2353 if (spec->kctls.list) {
2354 struct snd_kcontrol_new *kctl = spec->kctls.list;
2355 int i;
2356 for (i = 0; i < spec->kctls.used; i++)
2357 kfree(kctl[i].name);
2358 }
2359 snd_array_free(&spec->kctls);
2360}
2361
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362static void alc_free(struct hda_codec *codec)
2363{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002364 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002365
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002366 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002367 return;
2368
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002369 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002370 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002371 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002372 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002373 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374}
2375
Hector Martinf5de24b2009-12-20 22:51:31 +01002376#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002377static void alc_power_eapd(struct hda_codec *codec)
2378{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002379 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002380}
2381
Hector Martinf5de24b2009-12-20 22:51:31 +01002382static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2383{
2384 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002385 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002386 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002387 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002388 return 0;
2389}
2390#endif
2391
Takashi Iwai2a439522011-07-26 09:52:50 +02002392#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002393static int alc_resume(struct hda_codec *codec)
2394{
Takashi Iwai1c716152011-04-07 10:37:16 +02002395 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002396 codec->patch_ops.init(codec);
2397 snd_hda_codec_resume_amp(codec);
2398 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002399 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002400 return 0;
2401}
Takashi Iwaie044c392008-10-27 16:56:24 +01002402#endif
2403
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404/*
2405 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002406static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 .build_controls = alc_build_controls,
2408 .build_pcms = alc_build_pcms,
2409 .init = alc_init,
2410 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002411 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002412#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002413 .resume = alc_resume,
2414#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002415#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002416 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002417 .check_power_status = alc_check_power_status,
2418#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002419 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420};
2421
Kailang Yangc027ddc2010-03-19 11:33:06 +01002422/* replace the codec chip_name with the given string */
2423static int alc_codec_rename(struct hda_codec *codec, const char *name)
2424{
2425 kfree(codec->chip_name);
2426 codec->chip_name = kstrdup(name, GFP_KERNEL);
2427 if (!codec->chip_name) {
2428 alc_free(codec);
2429 return -ENOMEM;
2430 }
2431 return 0;
2432}
2433
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002434/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002435 * Automatic parse of I/O pins from the BIOS configuration
2436 */
2437
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002438enum {
2439 ALC_CTL_WIDGET_VOL,
2440 ALC_CTL_WIDGET_MUTE,
2441 ALC_CTL_BIND_MUTE,
2442};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002443static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002444 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2445 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002446 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002447};
2448
2449/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002450static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002451 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002452{
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002453 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002454
Takashi Iwaice764ab2011-04-27 16:35:23 +02002455 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002456 if (!knew)
2457 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002458 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002459 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002460 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002461 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002462 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002463 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002464 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002465 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002466 return 0;
2467}
2468
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002469static int add_control_with_pfx(struct alc_spec *spec, int type,
2470 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002471 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002472{
2473 char name[32];
2474 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002475 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002476}
2477
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002478#define add_pb_vol_ctrl(spec, type, pfx, val) \
2479 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2480#define add_pb_sw_ctrl(spec, type, pfx, val) \
2481 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2482#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2483 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2484#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2485 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002486
Takashi Iwai6843ca12011-06-24 11:03:58 +02002487static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2488 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002489{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002490 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002491 static const char * const chname[4] = {
2492 "Front", "Surround", NULL /*CLFE*/, "Side"
2493 };
Takashi Iwaice764ab2011-04-27 16:35:23 +02002494
Takashi Iwai6843ca12011-06-24 11:03:58 +02002495 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002496 if (cfg->line_outs == 1 && !spec->multi_ios &&
2497 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002498 return "Master";
2499
2500 switch (cfg->line_out_type) {
2501 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002502 if (cfg->line_outs == 1)
2503 return "Speaker";
2504 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002505 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002506 /* for multi-io case, only the primary out */
2507 if (ch && spec->multi_ios)
2508 break;
2509 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002510 return "Headphone";
2511 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002512 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002513 return "PCM";
2514 break;
2515 }
Takashi Iwai6843ca12011-06-24 11:03:58 +02002516 return chname[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002517}
2518
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002519/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002520static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002521 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002522 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002523{
Kailang Yangdf694da2005-12-05 19:42:22 +01002524 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002525
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002526 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002527 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2528 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002529 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002530 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002531 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2532 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002533 return err;
2534 return 0;
2535}
2536
Takashi Iwai05f5f472009-08-25 13:10:18 +02002537static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002538{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002539 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2540 return (pincap & AC_PINCAP_IN) != 0;
2541}
2542
Takashi Iwai1d045db2011-07-07 18:23:21 +02002543/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002544static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002545{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002546 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002547 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002548 hda_nid_t *adc_nids = spec->private_adc_nids;
2549 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2550 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2551 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002552 int i, nums = 0;
2553
2554 nid = codec->start_nid;
2555 for (i = 0; i < codec->num_nodes; i++, nid++) {
2556 hda_nid_t src;
2557 const hda_nid_t *list;
2558 unsigned int caps = get_wcaps(codec, nid);
2559 int type = get_wcaps_type(caps);
2560
2561 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2562 continue;
2563 adc_nids[nums] = nid;
2564 cap_nids[nums] = nid;
2565 src = nid;
2566 for (;;) {
2567 int n;
2568 type = get_wcaps_type(get_wcaps(codec, src));
2569 if (type == AC_WID_PIN)
2570 break;
2571 if (type == AC_WID_AUD_SEL) {
2572 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002573 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002574 break;
2575 }
2576 n = snd_hda_get_conn_list(codec, src, &list);
2577 if (n > 1) {
2578 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002579 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002580 break;
2581 } else if (n != 1)
2582 break;
2583 src = *list;
2584 }
2585 if (++nums >= max_nums)
2586 break;
2587 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002588 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002589 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002590 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002591 return nums;
2592}
2593
Takashi Iwai05f5f472009-08-25 13:10:18 +02002594/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002595static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002596{
2597 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002598 const struct auto_pin_cfg *cfg = &spec->autocfg;
2599 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002600 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002601 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002602 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002603 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002604
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002605 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002606 if (num_adcs < 0)
2607 return 0;
2608
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002609 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002610 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002611 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002612
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002613 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002614 if (!alc_is_input_pin(codec, pin))
2615 continue;
2616
David Henningsson5322bf22011-01-05 11:03:56 +01002617 label = hda_get_autocfg_input_label(codec, cfg, i);
2618 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002619 type_idx++;
2620 else
2621 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002622 prev_label = label;
2623
Takashi Iwai05f5f472009-08-25 13:10:18 +02002624 if (mixer) {
2625 idx = get_connection_index(codec, mixer, pin);
2626 if (idx >= 0) {
2627 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002628 label, type_idx,
2629 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002630 if (err < 0)
2631 return err;
2632 }
2633 }
2634
Takashi Iwaib7821702011-07-06 15:12:46 +02002635 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002636 hda_nid_t cap = spec->capsrc_nids ?
2637 spec->capsrc_nids[c] : spec->adc_nids[c];
2638 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002639 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002640 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002641 snd_hda_add_imux_item(imux, label, idx, NULL);
2642 break;
2643 }
2644 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002645 }
Takashi Iwai21268962011-07-07 15:01:13 +02002646
2647 spec->num_mux_defs = 1;
2648 spec->input_mux = imux;
2649
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002650 return 0;
2651}
2652
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002653static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2654 unsigned int pin_type)
2655{
2656 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2657 pin_type);
2658 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002659 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2660 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002661 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002662}
2663
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002664static int get_pin_type(int line_out_type)
2665{
2666 if (line_out_type == AUTO_PIN_HP_OUT)
2667 return PIN_HP;
2668 else
2669 return PIN_OUT;
2670}
2671
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002672static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002673{
2674 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002675 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002676 int i;
2677
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002678 for (i = 0; i < cfg->num_inputs; i++) {
2679 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002680 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002681 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002682 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002683 snd_hda_codec_write(codec, nid, 0,
2684 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002685 AMP_OUT_MUTE);
2686 }
2687 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002688
2689 /* mute all loopback inputs */
2690 if (spec->mixer_nid) {
2691 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2692 for (i = 0; i < nums; i++)
2693 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2694 AC_VERB_SET_AMP_GAIN_MUTE,
2695 AMP_IN_MUTE(i));
2696 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002697}
2698
Takashi Iwai7085ec12009-10-02 09:03:58 +02002699/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002700static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002701{
Takashi Iwai604401a2011-04-27 15:14:23 +02002702 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002703 int i, num;
2704
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002705 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2706 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002707 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2708 for (i = 0; i < num; i++) {
2709 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2710 return list[i];
2711 }
2712 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002713}
2714
Takashi Iwai604401a2011-04-27 15:14:23 +02002715/* go down to the selector widget before the mixer */
2716static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2717{
2718 hda_nid_t srcs[5];
2719 int num = snd_hda_get_connections(codec, pin, srcs,
2720 ARRAY_SIZE(srcs));
2721 if (num != 1 ||
2722 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2723 return pin;
2724 return srcs[0];
2725}
2726
Takashi Iwai7085ec12009-10-02 09:03:58 +02002727/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002728static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002729 hda_nid_t dac)
2730{
David Henningssoncc1c4522010-11-24 14:17:47 +01002731 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002732 int i, num;
2733
Takashi Iwai604401a2011-04-27 15:14:23 +02002734 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002735 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2736 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002737 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002738 return mix[i];
2739 }
2740 return 0;
2741}
2742
Takashi Iwaice764ab2011-04-27 16:35:23 +02002743/* select the connection from pin to DAC if needed */
2744static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2745 hda_nid_t dac)
2746{
2747 hda_nid_t mix[5];
2748 int i, num;
2749
2750 pin = alc_go_down_to_selector(codec, pin);
2751 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2752 if (num < 2)
2753 return 0;
2754 for (i = 0; i < num; i++) {
2755 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2756 snd_hda_codec_update_cache(codec, pin, 0,
2757 AC_VERB_SET_CONNECT_SEL, i);
2758 return 0;
2759 }
2760 }
2761 return 0;
2762}
2763
Takashi Iwai7085ec12009-10-02 09:03:58 +02002764/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002765static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002766{
2767 struct alc_spec *spec = codec->spec;
2768 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002769 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002770
Takashi Iwai604401a2011-04-27 15:14:23 +02002771 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002772 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002773 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002774 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002775 if (!nid)
2776 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002777 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2778 spec->multiout.num_dacs))
2779 continue;
2780 if (spec->multiout.hp_nid == nid)
2781 continue;
2782 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2783 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2784 continue;
2785 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002786 }
2787 return 0;
2788}
2789
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002790static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2791{
2792 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2793 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2794 return alc_auto_look_for_dac(codec, pin);
2795 return 0;
2796}
2797
Takashi Iwai7085ec12009-10-02 09:03:58 +02002798/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002799static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002800{
2801 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002802 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002803 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002804 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002805
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002806 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002807 /* set num_dacs once to full for alc_auto_look_for_dac() */
2808 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002809 spec->multiout.hp_nid = 0;
2810 spec->multiout.extra_out_nid[0] = 0;
2811 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2812 spec->multiout.dac_nids = spec->private_dac_nids;
2813
2814 /* fill hard-wired DACs first */
2815 if (!redone) {
2816 for (i = 0; i < cfg->line_outs; i++)
2817 spec->private_dac_nids[i] =
2818 get_dac_if_single(codec, cfg->line_out_pins[i]);
2819 if (cfg->hp_outs)
2820 spec->multiout.hp_nid =
2821 get_dac_if_single(codec, cfg->hp_pins[0]);
2822 if (cfg->speaker_outs)
2823 spec->multiout.extra_out_nid[0] =
2824 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002825 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002826
2827 for (i = 0; i < cfg->line_outs; i++) {
2828 hda_nid_t pin = cfg->line_out_pins[i];
2829 if (spec->private_dac_nids[i])
2830 continue;
2831 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2832 if (!spec->private_dac_nids[i] && !redone) {
2833 /* if we can't find primary DACs, re-probe without
2834 * checking the hard-wired DACs
2835 */
2836 redone = true;
2837 goto again;
2838 }
2839 }
2840
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002841 /* re-count num_dacs and squash invalid entries */
2842 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002843 for (i = 0; i < cfg->line_outs; i++) {
2844 if (spec->private_dac_nids[i])
2845 spec->multiout.num_dacs++;
2846 else
2847 memmove(spec->private_dac_nids + i,
2848 spec->private_dac_nids + i + 1,
2849 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2850 }
2851
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002852 if (cfg->hp_outs && !spec->multiout.hp_nid)
2853 spec->multiout.hp_nid =
2854 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2855 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2856 spec->multiout.extra_out_nid[0] =
2857 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2858
Takashi Iwai7085ec12009-10-02 09:03:58 +02002859 return 0;
2860}
2861
Takashi Iwai343a04b2011-07-06 14:28:39 +02002862static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002863 const char *pfx, int cidx,
2864 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002865{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002866 if (!nid)
2867 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002868 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2869 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002870}
2871
Takashi Iwai343a04b2011-07-06 14:28:39 +02002872#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2873 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002874
2875/* create a mute-switch for the given mixer widget;
2876 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2877 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002878static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002879 const char *pfx, int cidx,
2880 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002881{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002882 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002883 int type;
2884 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002885 if (!nid)
2886 return 0;
2887 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2888 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2889 type = ALC_CTL_WIDGET_MUTE;
2890 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2891 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002892 type = ALC_CTL_WIDGET_MUTE;
2893 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2894 } else {
2895 type = ALC_CTL_BIND_MUTE;
2896 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2897 }
2898 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002899}
2900
Takashi Iwai343a04b2011-07-06 14:28:39 +02002901#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2902 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002903
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002904static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2905 hda_nid_t pin, hda_nid_t dac)
2906{
2907 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2908 if (nid_has_mute(codec, pin, HDA_OUTPUT))
2909 return pin;
2910 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
2911 return mix;
2912 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
2913 return dac;
2914 return 0;
2915}
2916
2917static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
2918 hda_nid_t pin, hda_nid_t dac)
2919{
2920 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2921 if (nid_has_volume(codec, dac, HDA_OUTPUT))
2922 return dac;
2923 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
2924 return mix;
2925 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
2926 return pin;
2927 return 0;
2928}
2929
Takashi Iwai7085ec12009-10-02 09:03:58 +02002930/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002931static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002932 const struct auto_pin_cfg *cfg)
2933{
2934 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002935 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002936
Takashi Iwaice764ab2011-04-27 16:35:23 +02002937 noutputs = cfg->line_outs;
2938 if (spec->multi_ios > 0)
2939 noutputs += spec->multi_ios;
2940
2941 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002942 const char *name;
2943 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002944 hda_nid_t dac, pin;
2945 hda_nid_t sw, vol;
2946
2947 dac = spec->multiout.dac_nids[i];
2948 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002949 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002950 if (i >= cfg->line_outs)
2951 pin = spec->multi_io[i - 1].pin;
2952 else
2953 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002954
2955 sw = alc_look_for_out_mute_nid(codec, pin, dac);
2956 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02002957 name = alc_get_line_out_pfx(spec, i, true, &index);
2958 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002959 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002960 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002961 if (err < 0)
2962 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002963 err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002964 if (err < 0)
2965 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002966 err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002967 if (err < 0)
2968 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002969 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002970 if (err < 0)
2971 return err;
2972 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002973 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002974 if (err < 0)
2975 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002976 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002977 if (err < 0)
2978 return err;
2979 }
2980 }
2981 return 0;
2982}
2983
2984/* add playback controls for speaker and HP outputs */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002985static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002986 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002987{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002988 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002989 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002990 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002991
2992 if (!pin)
2993 return 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002994 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02002995 /* the corresponding DAC is already occupied */
2996 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
2997 return 0; /* no way */
2998 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002999 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003000 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3001 }
3002
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003003 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3004 vol = alc_look_for_out_vol_nid(codec, pin, dac);
3005 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003006 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003007 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003008 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003009 if (err < 0)
3010 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003011 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003012}
3013
Takashi Iwai343a04b2011-07-06 14:28:39 +02003014static int alc_auto_create_hp_out(struct hda_codec *codec)
3015{
3016 struct alc_spec *spec = codec->spec;
3017 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3018 spec->multiout.hp_nid,
3019 "Headphone");
3020}
3021
3022static int alc_auto_create_speaker_out(struct hda_codec *codec)
3023{
3024 struct alc_spec *spec = codec->spec;
3025 return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
3026 spec->multiout.extra_out_nid[0],
3027 "Speaker");
3028}
3029
Takashi Iwai343a04b2011-07-06 14:28:39 +02003030static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003031 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003032 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003033{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003034 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003035 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003036 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003037
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003038 alc_set_pin_output(codec, pin, pin_type);
3039 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003040 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003041 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003042 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003043 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003044 mix = srcs[i];
3045 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003046 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003047 if (!mix)
3048 return;
3049
3050 /* need the manual connection? */
3051 if (num > 1)
3052 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3053 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003054 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3055 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003056 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003057 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003058 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003059 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003060 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003061 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3062 if (nid)
3063 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3064 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003065}
3066
Takashi Iwai343a04b2011-07-06 14:28:39 +02003067static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003068{
3069 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003070 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003071 int i;
3072
3073 for (i = 0; i <= HDA_SIDE; i++) {
3074 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3075 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003076 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003077 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003078 }
3079}
3080
Takashi Iwai343a04b2011-07-06 14:28:39 +02003081static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003082{
3083 struct alc_spec *spec = codec->spec;
3084 hda_nid_t pin;
3085
3086 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003087 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003088 alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003089 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003090 pin = spec->autocfg.speaker_pins[0];
3091 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003092 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003093 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003094}
3095
Takashi Iwaice764ab2011-04-27 16:35:23 +02003096/*
3097 * multi-io helper
3098 */
3099static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3100 unsigned int location)
3101{
3102 struct alc_spec *spec = codec->spec;
3103 struct auto_pin_cfg *cfg = &spec->autocfg;
3104 int type, i, num_pins = 0;
3105
3106 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3107 for (i = 0; i < cfg->num_inputs; i++) {
3108 hda_nid_t nid = cfg->inputs[i].pin;
3109 hda_nid_t dac;
3110 unsigned int defcfg, caps;
3111 if (cfg->inputs[i].type != type)
3112 continue;
3113 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3114 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3115 continue;
3116 if (location && get_defcfg_location(defcfg) != location)
3117 continue;
3118 caps = snd_hda_query_pin_caps(codec, nid);
3119 if (!(caps & AC_PINCAP_OUT))
3120 continue;
3121 dac = alc_auto_look_for_dac(codec, nid);
3122 if (!dac)
3123 continue;
3124 spec->multi_io[num_pins].pin = nid;
3125 spec->multi_io[num_pins].dac = dac;
3126 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003127 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003128 }
3129 }
3130 spec->multiout.num_dacs = 1;
3131 if (num_pins < 2)
3132 return 0;
3133 return num_pins;
3134}
3135
3136static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3137 struct snd_ctl_elem_info *uinfo)
3138{
3139 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3140 struct alc_spec *spec = codec->spec;
3141
3142 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3143 uinfo->count = 1;
3144 uinfo->value.enumerated.items = spec->multi_ios + 1;
3145 if (uinfo->value.enumerated.item > spec->multi_ios)
3146 uinfo->value.enumerated.item = spec->multi_ios;
3147 sprintf(uinfo->value.enumerated.name, "%dch",
3148 (uinfo->value.enumerated.item + 1) * 2);
3149 return 0;
3150}
3151
3152static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3153 struct snd_ctl_elem_value *ucontrol)
3154{
3155 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3156 struct alc_spec *spec = codec->spec;
3157 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3158 return 0;
3159}
3160
3161static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3162{
3163 struct alc_spec *spec = codec->spec;
3164 hda_nid_t nid = spec->multi_io[idx].pin;
3165
3166 if (!spec->multi_io[idx].ctl_in)
3167 spec->multi_io[idx].ctl_in =
3168 snd_hda_codec_read(codec, nid, 0,
3169 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3170 if (output) {
3171 snd_hda_codec_update_cache(codec, nid, 0,
3172 AC_VERB_SET_PIN_WIDGET_CONTROL,
3173 PIN_OUT);
3174 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3175 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3176 HDA_AMP_MUTE, 0);
3177 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3178 } else {
3179 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3180 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3181 HDA_AMP_MUTE, HDA_AMP_MUTE);
3182 snd_hda_codec_update_cache(codec, nid, 0,
3183 AC_VERB_SET_PIN_WIDGET_CONTROL,
3184 spec->multi_io[idx].ctl_in);
3185 }
3186 return 0;
3187}
3188
3189static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3190 struct snd_ctl_elem_value *ucontrol)
3191{
3192 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3193 struct alc_spec *spec = codec->spec;
3194 int i, ch;
3195
3196 ch = ucontrol->value.enumerated.item[0];
3197 if (ch < 0 || ch > spec->multi_ios)
3198 return -EINVAL;
3199 if (ch == (spec->ext_channel_count - 1) / 2)
3200 return 0;
3201 spec->ext_channel_count = (ch + 1) * 2;
3202 for (i = 0; i < spec->multi_ios; i++)
3203 alc_set_multi_io(codec, i, i < ch);
3204 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003205 if (spec->need_dac_fix && !spec->const_channel_count)
3206 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003207 return 1;
3208}
3209
Takashi Iwaia9111322011-05-02 11:30:18 +02003210static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003211 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3212 .name = "Channel Mode",
3213 .info = alc_auto_ch_mode_info,
3214 .get = alc_auto_ch_mode_get,
3215 .put = alc_auto_ch_mode_put,
3216};
3217
Takashi Iwaicb053a82011-06-27 11:32:07 +02003218static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
3219 int (*fill_dac)(struct hda_codec *))
Takashi Iwaice764ab2011-04-27 16:35:23 +02003220{
3221 struct alc_spec *spec = codec->spec;
3222 struct auto_pin_cfg *cfg = &spec->autocfg;
3223 unsigned int location, defcfg;
3224 int num_pins;
3225
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003226 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3227 /* use HP as primary out */
3228 cfg->speaker_outs = cfg->line_outs;
3229 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3230 sizeof(cfg->speaker_pins));
3231 cfg->line_outs = cfg->hp_outs;
3232 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3233 cfg->hp_outs = 0;
3234 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3235 cfg->line_out_type = AUTO_PIN_HP_OUT;
Takashi Iwaicb053a82011-06-27 11:32:07 +02003236 if (fill_dac)
3237 fill_dac(codec);
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003238 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003239 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003240 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003241 return 0;
3242
3243 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3244 location = get_defcfg_location(defcfg);
3245
3246 num_pins = alc_auto_fill_multi_ios(codec, location);
3247 if (num_pins > 0) {
3248 struct snd_kcontrol_new *knew;
3249
3250 knew = alc_kcontrol_new(spec);
3251 if (!knew)
3252 return -ENOMEM;
3253 *knew = alc_auto_channel_mode_enum;
3254 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3255 if (!knew->name)
3256 return -ENOMEM;
3257
3258 spec->multi_ios = num_pins;
3259 spec->ext_channel_count = 2;
3260 spec->multiout.num_dacs = num_pins + 1;
3261 }
3262 return 0;
3263}
3264
Takashi Iwai1d045db2011-07-07 18:23:21 +02003265/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3266 * active input pins
3267 */
3268static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3269{
3270 struct alc_spec *spec = codec->spec;
3271 const struct hda_input_mux *imux;
3272 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3273 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3274 int i, n, nums;
3275
3276 imux = spec->input_mux;
3277 if (!imux)
3278 return;
3279 if (spec->dyn_adc_switch)
3280 return;
3281
3282 nums = 0;
3283 for (n = 0; n < spec->num_adc_nids; n++) {
3284 hda_nid_t cap = spec->private_capsrc_nids[n];
3285 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3286 for (i = 0; i < imux->num_items; i++) {
3287 hda_nid_t pin = spec->imux_pins[i];
3288 if (pin) {
3289 if (get_connection_index(codec, cap, pin) < 0)
3290 break;
3291 } else if (num_conns <= imux->items[i].index)
3292 break;
3293 }
3294 if (i >= imux->num_items) {
3295 adc_nids[nums] = spec->private_adc_nids[n];
3296 capsrc_nids[nums++] = cap;
3297 }
3298 }
3299 if (!nums) {
3300 /* check whether ADC-switch is possible */
3301 if (!alc_check_dyn_adc_switch(codec)) {
3302 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3303 " using fallback 0x%x\n",
3304 codec->chip_name, spec->private_adc_nids[0]);
3305 spec->num_adc_nids = 1;
3306 spec->auto_mic = 0;
3307 return;
3308 }
3309 } else if (nums != spec->num_adc_nids) {
3310 memcpy(spec->private_adc_nids, adc_nids,
3311 nums * sizeof(hda_nid_t));
3312 memcpy(spec->private_capsrc_nids, capsrc_nids,
3313 nums * sizeof(hda_nid_t));
3314 spec->num_adc_nids = nums;
3315 }
3316
3317 if (spec->auto_mic)
3318 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3319 else if (spec->input_mux->num_items == 1)
3320 spec->num_adc_nids = 1; /* reduce to a single ADC */
3321}
3322
3323/*
3324 * initialize ADC paths
3325 */
3326static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3327{
3328 struct alc_spec *spec = codec->spec;
3329 hda_nid_t nid;
3330
3331 nid = spec->adc_nids[adc_idx];
3332 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003333 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003334 snd_hda_codec_write(codec, nid, 0,
3335 AC_VERB_SET_AMP_GAIN_MUTE,
3336 AMP_IN_MUTE(0));
3337 return;
3338 }
3339 if (!spec->capsrc_nids)
3340 return;
3341 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003342 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003343 snd_hda_codec_write(codec, nid, 0,
3344 AC_VERB_SET_AMP_GAIN_MUTE,
3345 AMP_OUT_MUTE);
3346}
3347
3348static void alc_auto_init_input_src(struct hda_codec *codec)
3349{
3350 struct alc_spec *spec = codec->spec;
3351 int c, nums;
3352
3353 for (c = 0; c < spec->num_adc_nids; c++)
3354 alc_auto_init_adc(codec, c);
3355 if (spec->dyn_adc_switch)
3356 nums = 1;
3357 else
3358 nums = spec->num_adc_nids;
3359 for (c = 0; c < nums; c++)
3360 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3361}
3362
3363/* add mic boosts if needed */
3364static int alc_auto_add_mic_boost(struct hda_codec *codec)
3365{
3366 struct alc_spec *spec = codec->spec;
3367 struct auto_pin_cfg *cfg = &spec->autocfg;
3368 int i, err;
3369 int type_idx = 0;
3370 hda_nid_t nid;
3371 const char *prev_label = NULL;
3372
3373 for (i = 0; i < cfg->num_inputs; i++) {
3374 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3375 break;
3376 nid = cfg->inputs[i].pin;
3377 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3378 const char *label;
3379 char boost_label[32];
3380
3381 label = hda_get_autocfg_input_label(codec, cfg, i);
3382 if (prev_label && !strcmp(label, prev_label))
3383 type_idx++;
3384 else
3385 type_idx = 0;
3386 prev_label = label;
3387
3388 snprintf(boost_label, sizeof(boost_label),
3389 "%s Boost Volume", label);
3390 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3391 boost_label, type_idx,
3392 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3393 if (err < 0)
3394 return err;
3395 }
3396 }
3397 return 0;
3398}
3399
3400/* select or unmute the given capsrc route */
3401static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3402 int idx)
3403{
3404 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3405 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3406 HDA_AMP_MUTE, 0);
3407 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3408 snd_hda_codec_write_cache(codec, cap, 0,
3409 AC_VERB_SET_CONNECT_SEL, idx);
3410 }
3411}
3412
3413/* set the default connection to that pin */
3414static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3415{
3416 struct alc_spec *spec = codec->spec;
3417 int i;
3418
3419 if (!pin)
3420 return 0;
3421 for (i = 0; i < spec->num_adc_nids; i++) {
3422 hda_nid_t cap = spec->capsrc_nids ?
3423 spec->capsrc_nids[i] : spec->adc_nids[i];
3424 int idx;
3425
3426 idx = get_connection_index(codec, cap, pin);
3427 if (idx < 0)
3428 continue;
3429 select_or_unmute_capsrc(codec, cap, idx);
3430 return i; /* return the found index */
3431 }
3432 return -1; /* not found */
3433}
3434
3435/* initialize some special cases for input sources */
3436static void alc_init_special_input_src(struct hda_codec *codec)
3437{
3438 struct alc_spec *spec = codec->spec;
3439 int i;
3440
3441 for (i = 0; i < spec->autocfg.num_inputs; i++)
3442 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3443}
3444
3445/* assign appropriate capture mixers */
3446static void set_capture_mixer(struct hda_codec *codec)
3447{
3448 struct alc_spec *spec = codec->spec;
3449 static const struct snd_kcontrol_new *caps[2][3] = {
3450 { alc_capture_mixer_nosrc1,
3451 alc_capture_mixer_nosrc2,
3452 alc_capture_mixer_nosrc3 },
3453 { alc_capture_mixer1,
3454 alc_capture_mixer2,
3455 alc_capture_mixer3 },
3456 };
3457
3458 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003459 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003460 if (!spec->capsrc_nids)
3461 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003462 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003463 return; /* no volume in capsrc, too */
3464 spec->vol_in_capsrc = 1;
3465 }
3466
3467 if (spec->num_adc_nids > 0) {
3468 int mux = 0;
3469 int num_adcs = 0;
3470
3471 if (spec->input_mux && spec->input_mux->num_items > 1)
3472 mux = 1;
3473 if (spec->auto_mic) {
3474 num_adcs = 1;
3475 mux = 0;
3476 } else if (spec->dyn_adc_switch)
3477 num_adcs = 1;
3478 if (!num_adcs) {
3479 if (spec->num_adc_nids > 3)
3480 spec->num_adc_nids = 3;
3481 else if (!spec->num_adc_nids)
3482 return;
3483 num_adcs = spec->num_adc_nids;
3484 }
3485 spec->cap_mixer = caps[mux][num_adcs - 1];
3486 }
3487}
3488
3489/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003490 * standard auto-parser initializations
3491 */
3492static void alc_auto_init_std(struct hda_codec *codec)
3493{
3494 struct alc_spec *spec = codec->spec;
3495 alc_auto_init_multi_out(codec);
3496 alc_auto_init_extra_out(codec);
3497 alc_auto_init_analog_input(codec);
3498 alc_auto_init_input_src(codec);
3499 alc_auto_init_digital(codec);
3500 if (spec->unsol_event)
3501 alc_inithook(codec);
3502}
3503
3504/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003505 * Digital-beep handlers
3506 */
3507#ifdef CONFIG_SND_HDA_INPUT_BEEP
3508#define set_beep_amp(spec, nid, idx, dir) \
3509 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3510
3511static const struct snd_pci_quirk beep_white_list[] = {
3512 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3513 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3514 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3515 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3516 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3517 {}
3518};
3519
3520static inline int has_cdefine_beep(struct hda_codec *codec)
3521{
3522 struct alc_spec *spec = codec->spec;
3523 const struct snd_pci_quirk *q;
3524 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3525 if (q)
3526 return q->value;
3527 return spec->cdefine.enable_pcbeep;
3528}
3529#else
3530#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3531#define has_cdefine_beep(codec) 0
3532#endif
3533
3534/* parse the BIOS configuration and set up the alc_spec */
3535/* return 1 if successful, 0 if the proper config is not found,
3536 * or a negative error code
3537 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003538static int alc_parse_auto_config(struct hda_codec *codec,
3539 const hda_nid_t *ignore_nids,
3540 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003541{
3542 struct alc_spec *spec = codec->spec;
3543 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003544
3545 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003546 ignore_nids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003547 if (err < 0)
3548 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003549 if (!spec->autocfg.line_outs) {
3550 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
3551 spec->multiout.max_channels = 2;
3552 spec->no_analog = 1;
3553 goto dig_only;
3554 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003555 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003556 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003557 err = alc_auto_fill_dac_nids(codec);
3558 if (err < 0)
3559 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003560 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
3561 if (err < 0)
3562 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003563 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
3564 if (err < 0)
3565 return err;
3566 err = alc_auto_create_hp_out(codec);
3567 if (err < 0)
3568 return err;
3569 err = alc_auto_create_speaker_out(codec);
3570 if (err < 0)
3571 return err;
3572 err = alc_auto_create_input_ctls(codec);
3573 if (err < 0)
3574 return err;
3575
3576 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3577
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003578 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02003579 alc_auto_parse_digital(codec);
3580
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003581 if (!spec->no_analog)
3582 alc_remove_invalid_adc_nids(codec);
3583
3584 if (ssid_nids)
3585 alc_ssid_check(codec, ssid_nids);
3586
3587 if (!spec->no_analog) {
3588 alc_auto_check_switches(codec);
3589 err = alc_auto_add_mic_boost(codec);
3590 if (err < 0)
3591 return err;
3592 }
3593
Takashi Iwai1d045db2011-07-07 18:23:21 +02003594 if (spec->kctls.list)
3595 add_mixer(spec, spec->kctls.list);
3596
Takashi Iwai1d045db2011-07-07 18:23:21 +02003597 return 1;
3598}
3599
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003600static int alc880_parse_auto_config(struct hda_codec *codec)
3601{
3602 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3603 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3604 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
3605}
3606
Takashi Iwai1d045db2011-07-07 18:23:21 +02003607#ifdef CONFIG_SND_HDA_POWER_SAVE
3608static const struct hda_amp_list alc880_loopbacks[] = {
3609 { 0x0b, HDA_INPUT, 0 },
3610 { 0x0b, HDA_INPUT, 1 },
3611 { 0x0b, HDA_INPUT, 2 },
3612 { 0x0b, HDA_INPUT, 3 },
3613 { 0x0b, HDA_INPUT, 4 },
3614 { } /* end */
3615};
3616#endif
3617
3618/*
3619 * board setups
3620 */
3621#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3622#define alc_board_config \
3623 snd_hda_check_board_config
3624#define alc_board_codec_sid_config \
3625 snd_hda_check_board_codec_sid_config
3626#include "alc_quirks.c"
3627#else
3628#define alc_board_config(codec, nums, models, tbl) -1
3629#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3630#define setup_preset(codec, x) /* NOP */
3631#endif
3632
3633/*
3634 * OK, here we have finally the patch for ALC880
3635 */
3636#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3637#include "alc880_quirks.c"
3638#endif
3639
3640static int patch_alc880(struct hda_codec *codec)
3641{
3642 struct alc_spec *spec;
3643 int board_config;
3644 int err;
3645
3646 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3647 if (spec == NULL)
3648 return -ENOMEM;
3649
3650 codec->spec = spec;
3651
3652 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003653 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003654
3655 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3656 alc880_models, alc880_cfg_tbl);
3657 if (board_config < 0) {
3658 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3659 codec->chip_name);
3660 board_config = ALC_MODEL_AUTO;
3661 }
3662
3663 if (board_config == ALC_MODEL_AUTO) {
3664 /* automatic parse from the BIOS config */
3665 err = alc880_parse_auto_config(codec);
3666 if (err < 0) {
3667 alc_free(codec);
3668 return err;
3669 }
3670#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3671 else if (!err) {
3672 printk(KERN_INFO
3673 "hda_codec: Cannot set up configuration "
3674 "from BIOS. Using 3-stack mode...\n");
3675 board_config = ALC880_3ST;
3676 }
3677#endif
3678 }
3679
Takashi Iwai1d045db2011-07-07 18:23:21 +02003680 if (board_config != ALC_MODEL_AUTO)
3681 setup_preset(codec, &alc880_presets[board_config]);
3682
Takashi Iwai60a6a842011-07-27 14:01:24 +02003683 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003684 alc_auto_fill_adc_caps(codec);
3685 alc_rebuild_imux_for_auto_mic(codec);
3686 alc_remove_invalid_adc_nids(codec);
3687 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003688
3689 if (!spec->no_analog && !spec->cap_mixer)
3690 set_capture_mixer(codec);
3691
3692 if (!spec->no_analog) {
3693 err = snd_hda_attach_beep_device(codec, 0x1);
3694 if (err < 0) {
3695 alc_free(codec);
3696 return err;
3697 }
3698 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3699 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003700
3701 spec->vmaster_nid = 0x0c;
3702
3703 codec->patch_ops = alc_patch_ops;
3704 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003705 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003706#ifdef CONFIG_SND_HDA_POWER_SAVE
3707 if (!spec->loopback.amplist)
3708 spec->loopback.amplist = alc880_loopbacks;
3709#endif
3710
3711 return 0;
3712}
3713
3714
3715/*
3716 * ALC260 support
3717 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003718static int alc260_parse_auto_config(struct hda_codec *codec)
3719{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003720 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003721 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
3722 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003723}
3724
Takashi Iwai1d045db2011-07-07 18:23:21 +02003725#ifdef CONFIG_SND_HDA_POWER_SAVE
3726static const struct hda_amp_list alc260_loopbacks[] = {
3727 { 0x07, HDA_INPUT, 0 },
3728 { 0x07, HDA_INPUT, 1 },
3729 { 0x07, HDA_INPUT, 2 },
3730 { 0x07, HDA_INPUT, 3 },
3731 { 0x07, HDA_INPUT, 4 },
3732 { } /* end */
3733};
3734#endif
3735
3736/*
3737 * Pin config fixes
3738 */
3739enum {
3740 PINFIX_HP_DC5750,
3741};
3742
3743static const struct alc_fixup alc260_fixups[] = {
3744 [PINFIX_HP_DC5750] = {
3745 .type = ALC_FIXUP_PINS,
3746 .v.pins = (const struct alc_pincfg[]) {
3747 { 0x11, 0x90130110 }, /* speaker */
3748 { }
3749 }
3750 },
3751};
3752
3753static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3754 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3755 {}
3756};
3757
3758/*
3759 */
3760#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3761#include "alc260_quirks.c"
3762#endif
3763
3764static int patch_alc260(struct hda_codec *codec)
3765{
3766 struct alc_spec *spec;
3767 int err, board_config;
3768
3769 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3770 if (spec == NULL)
3771 return -ENOMEM;
3772
3773 codec->spec = spec;
3774
3775 spec->mixer_nid = 0x07;
3776
3777 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3778 alc260_models, alc260_cfg_tbl);
3779 if (board_config < 0) {
3780 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3781 codec->chip_name);
3782 board_config = ALC_MODEL_AUTO;
3783 }
3784
3785 if (board_config == ALC_MODEL_AUTO) {
3786 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3787 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3788 }
3789
3790 if (board_config == ALC_MODEL_AUTO) {
3791 /* automatic parse from the BIOS config */
3792 err = alc260_parse_auto_config(codec);
3793 if (err < 0) {
3794 alc_free(codec);
3795 return err;
3796 }
3797#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3798 else if (!err) {
3799 printk(KERN_INFO
3800 "hda_codec: Cannot set up configuration "
3801 "from BIOS. Using base mode...\n");
3802 board_config = ALC260_BASIC;
3803 }
3804#endif
3805 }
3806
Takashi Iwai1d045db2011-07-07 18:23:21 +02003807 if (board_config != ALC_MODEL_AUTO)
3808 setup_preset(codec, &alc260_presets[board_config]);
3809
Takashi Iwai60a6a842011-07-27 14:01:24 +02003810 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003811 alc_auto_fill_adc_caps(codec);
3812 alc_rebuild_imux_for_auto_mic(codec);
3813 alc_remove_invalid_adc_nids(codec);
3814 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003815
3816 if (!spec->no_analog && !spec->cap_mixer)
3817 set_capture_mixer(codec);
3818
3819 if (!spec->no_analog) {
3820 err = snd_hda_attach_beep_device(codec, 0x1);
3821 if (err < 0) {
3822 alc_free(codec);
3823 return err;
3824 }
3825 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3826 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003827
3828 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3829
3830 spec->vmaster_nid = 0x08;
3831
3832 codec->patch_ops = alc_patch_ops;
3833 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02003834 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003835 spec->shutup = alc_eapd_shutup;
3836#ifdef CONFIG_SND_HDA_POWER_SAVE
3837 if (!spec->loopback.amplist)
3838 spec->loopback.amplist = alc260_loopbacks;
3839#endif
3840
3841 return 0;
3842}
3843
3844
3845/*
3846 * ALC882/883/885/888/889 support
3847 *
3848 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3849 * configuration. Each pin widget can choose any input DACs and a mixer.
3850 * Each ADC is connected from a mixer of all inputs. This makes possible
3851 * 6-channel independent captures.
3852 *
3853 * In addition, an independent DAC for the multi-playback (not used in this
3854 * driver yet).
3855 */
3856#ifdef CONFIG_SND_HDA_POWER_SAVE
3857#define alc882_loopbacks alc880_loopbacks
3858#endif
3859
3860/*
3861 * Pin config fixes
3862 */
3863enum {
3864 PINFIX_ABIT_AW9D_MAX,
3865 PINFIX_LENOVO_Y530,
3866 PINFIX_PB_M5210,
3867 PINFIX_ACER_ASPIRE_7736,
3868};
3869
3870static const struct alc_fixup alc882_fixups[] = {
3871 [PINFIX_ABIT_AW9D_MAX] = {
3872 .type = ALC_FIXUP_PINS,
3873 .v.pins = (const struct alc_pincfg[]) {
3874 { 0x15, 0x01080104 }, /* side */
3875 { 0x16, 0x01011012 }, /* rear */
3876 { 0x17, 0x01016011 }, /* clfe */
3877 { }
3878 }
3879 },
3880 [PINFIX_LENOVO_Y530] = {
3881 .type = ALC_FIXUP_PINS,
3882 .v.pins = (const struct alc_pincfg[]) {
3883 { 0x15, 0x99130112 }, /* rear int speakers */
3884 { 0x16, 0x99130111 }, /* subwoofer */
3885 { }
3886 }
3887 },
3888 [PINFIX_PB_M5210] = {
3889 .type = ALC_FIXUP_VERBS,
3890 .v.verbs = (const struct hda_verb[]) {
3891 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
3892 {}
3893 }
3894 },
3895 [PINFIX_ACER_ASPIRE_7736] = {
3896 .type = ALC_FIXUP_SKU,
3897 .v.sku = ALC_FIXUP_SKU_IGNORE,
3898 },
3899};
3900
3901static const struct snd_pci_quirk alc882_fixup_tbl[] = {
3902 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
3903 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
3904 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
3905 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
3906 {}
3907};
3908
3909/*
3910 * BIOS auto configuration
3911 */
3912/* almost identical with ALC880 parser... */
3913static int alc882_parse_auto_config(struct hda_codec *codec)
3914{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003915 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003916 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3917 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003918}
3919
Takashi Iwai1d045db2011-07-07 18:23:21 +02003920/*
3921 */
3922#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3923#include "alc882_quirks.c"
3924#endif
3925
3926static int patch_alc882(struct hda_codec *codec)
3927{
3928 struct alc_spec *spec;
3929 int err, board_config;
3930
3931 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3932 if (spec == NULL)
3933 return -ENOMEM;
3934
3935 codec->spec = spec;
3936
3937 spec->mixer_nid = 0x0b;
3938
3939 switch (codec->vendor_id) {
3940 case 0x10ec0882:
3941 case 0x10ec0885:
3942 break;
3943 default:
3944 /* ALC883 and variants */
3945 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
3946 break;
3947 }
3948
3949 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
3950 alc882_models, alc882_cfg_tbl);
3951
3952 if (board_config < 0)
3953 board_config = alc_board_codec_sid_config(codec,
3954 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
3955
3956 if (board_config < 0) {
3957 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3958 codec->chip_name);
3959 board_config = ALC_MODEL_AUTO;
3960 }
3961
3962 if (board_config == ALC_MODEL_AUTO) {
3963 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
3964 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3965 }
3966
3967 alc_auto_parse_customize_define(codec);
3968
3969 if (board_config == ALC_MODEL_AUTO) {
3970 /* automatic parse from the BIOS config */
3971 err = alc882_parse_auto_config(codec);
3972 if (err < 0) {
3973 alc_free(codec);
3974 return err;
3975 }
3976#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3977 else if (!err) {
3978 printk(KERN_INFO
3979 "hda_codec: Cannot set up configuration "
3980 "from BIOS. Using base mode...\n");
3981 board_config = ALC882_3ST_DIG;
3982 }
3983#endif
3984 }
3985
Takashi Iwai1d045db2011-07-07 18:23:21 +02003986 if (board_config != ALC_MODEL_AUTO)
3987 setup_preset(codec, &alc882_presets[board_config]);
3988
Takashi Iwai60a6a842011-07-27 14:01:24 +02003989 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003990 alc_auto_fill_adc_caps(codec);
3991 alc_rebuild_imux_for_auto_mic(codec);
3992 alc_remove_invalid_adc_nids(codec);
3993 }
3994
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003995 if (!spec->no_analog && !spec->cap_mixer)
3996 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003997
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003998 if (!spec->no_analog && has_cdefine_beep(codec)) {
3999 err = snd_hda_attach_beep_device(codec, 0x1);
4000 if (err < 0) {
4001 alc_free(codec);
4002 return err;
4003 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004004 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004005 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004006
4007 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4008
4009 spec->vmaster_nid = 0x0c;
4010
4011 codec->patch_ops = alc_patch_ops;
4012 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004013 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004014
4015 alc_init_jacks(codec);
4016#ifdef CONFIG_SND_HDA_POWER_SAVE
4017 if (!spec->loopback.amplist)
4018 spec->loopback.amplist = alc882_loopbacks;
4019#endif
4020
4021 return 0;
4022}
4023
4024
4025/*
4026 * ALC262 support
4027 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004028static int alc262_parse_auto_config(struct hda_codec *codec)
4029{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004030 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004031 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4032 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004033}
4034
4035/*
4036 * Pin config fixes
4037 */
4038enum {
4039 PINFIX_FSC_H270,
4040 PINFIX_HP_Z200,
4041};
4042
4043static const struct alc_fixup alc262_fixups[] = {
4044 [PINFIX_FSC_H270] = {
4045 .type = ALC_FIXUP_PINS,
4046 .v.pins = (const struct alc_pincfg[]) {
4047 { 0x14, 0x99130110 }, /* speaker */
4048 { 0x15, 0x0221142f }, /* front HP */
4049 { 0x1b, 0x0121141f }, /* rear HP */
4050 { }
4051 }
4052 },
4053 [PINFIX_HP_Z200] = {
4054 .type = ALC_FIXUP_PINS,
4055 .v.pins = (const struct alc_pincfg[]) {
4056 { 0x16, 0x99130120 }, /* internal speaker */
4057 { }
4058 }
4059 },
4060};
4061
4062static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4063 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4064 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4065 {}
4066};
4067
4068
4069#ifdef CONFIG_SND_HDA_POWER_SAVE
4070#define alc262_loopbacks alc880_loopbacks
4071#endif
4072
Takashi Iwai1d045db2011-07-07 18:23:21 +02004073/*
4074 */
4075#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4076#include "alc262_quirks.c"
4077#endif
4078
4079static int patch_alc262(struct hda_codec *codec)
4080{
4081 struct alc_spec *spec;
4082 int board_config;
4083 int err;
4084
4085 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4086 if (spec == NULL)
4087 return -ENOMEM;
4088
4089 codec->spec = spec;
4090
4091 spec->mixer_nid = 0x0b;
4092
4093#if 0
4094 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4095 * under-run
4096 */
4097 {
4098 int tmp;
4099 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4100 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4101 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4102 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4103 }
4104#endif
4105 alc_auto_parse_customize_define(codec);
4106
4107 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4108
4109 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4110 alc262_models, alc262_cfg_tbl);
4111
4112 if (board_config < 0) {
4113 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4114 codec->chip_name);
4115 board_config = ALC_MODEL_AUTO;
4116 }
4117
4118 if (board_config == ALC_MODEL_AUTO) {
4119 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4120 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4121 }
4122
4123 if (board_config == ALC_MODEL_AUTO) {
4124 /* automatic parse from the BIOS config */
4125 err = alc262_parse_auto_config(codec);
4126 if (err < 0) {
4127 alc_free(codec);
4128 return err;
4129 }
4130#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4131 else if (!err) {
4132 printk(KERN_INFO
4133 "hda_codec: Cannot set up configuration "
4134 "from BIOS. Using base mode...\n");
4135 board_config = ALC262_BASIC;
4136 }
4137#endif
4138 }
4139
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004140 if (board_config != ALC_MODEL_AUTO)
4141 setup_preset(codec, &alc262_presets[board_config]);
4142
Takashi Iwai60a6a842011-07-27 14:01:24 +02004143 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004144 alc_auto_fill_adc_caps(codec);
4145 alc_rebuild_imux_for_auto_mic(codec);
4146 alc_remove_invalid_adc_nids(codec);
4147 }
4148
4149 if (!spec->no_analog && !spec->cap_mixer)
4150 set_capture_mixer(codec);
4151
Takashi Iwai1d045db2011-07-07 18:23:21 +02004152 if (!spec->no_analog && has_cdefine_beep(codec)) {
4153 err = snd_hda_attach_beep_device(codec, 0x1);
4154 if (err < 0) {
4155 alc_free(codec);
4156 return err;
4157 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004158 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004159 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004160
4161 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4162
4163 spec->vmaster_nid = 0x0c;
4164
4165 codec->patch_ops = alc_patch_ops;
4166 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004167 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004168 spec->shutup = alc_eapd_shutup;
4169
4170 alc_init_jacks(codec);
4171#ifdef CONFIG_SND_HDA_POWER_SAVE
4172 if (!spec->loopback.amplist)
4173 spec->loopback.amplist = alc262_loopbacks;
4174#endif
4175
4176 return 0;
4177}
4178
4179/*
4180 * ALC268
4181 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004182/* bind Beep switches of both NID 0x0f and 0x10 */
4183static const struct hda_bind_ctls alc268_bind_beep_sw = {
4184 .ops = &snd_hda_bind_sw,
4185 .values = {
4186 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4187 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4188 0
4189 },
4190};
4191
4192static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4193 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4194 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4195 { }
4196};
4197
4198/* set PCBEEP vol = 0, mute connections */
4199static const struct hda_verb alc268_beep_init_verbs[] = {
4200 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4201 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4202 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4203 { }
4204};
4205
4206/*
4207 * BIOS auto configuration
4208 */
4209static int alc268_parse_auto_config(struct hda_codec *codec)
4210{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004211 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004212 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004213 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4214 if (err > 0) {
4215 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4216 add_mixer(spec, alc268_beep_mixer);
4217 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004218 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004219 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004220 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004221}
4222
Takashi Iwai1d045db2011-07-07 18:23:21 +02004223/*
4224 */
4225#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4226#include "alc268_quirks.c"
4227#endif
4228
4229static int patch_alc268(struct hda_codec *codec)
4230{
4231 struct alc_spec *spec;
4232 int board_config;
4233 int i, has_beep, err;
4234
4235 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4236 if (spec == NULL)
4237 return -ENOMEM;
4238
4239 codec->spec = spec;
4240
4241 /* ALC268 has no aa-loopback mixer */
4242
4243 board_config = alc_board_config(codec, ALC268_MODEL_LAST,
4244 alc268_models, alc268_cfg_tbl);
4245
4246 if (board_config < 0)
4247 board_config = alc_board_codec_sid_config(codec,
Takashi Iwaid8897da2011-08-15 13:15:17 +02004248 ALC268_MODEL_LAST, alc268_models, NULL);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004249
4250 if (board_config < 0) {
4251 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4252 codec->chip_name);
4253 board_config = ALC_MODEL_AUTO;
4254 }
4255
4256 if (board_config == ALC_MODEL_AUTO) {
4257 /* automatic parse from the BIOS config */
4258 err = alc268_parse_auto_config(codec);
4259 if (err < 0) {
4260 alc_free(codec);
4261 return err;
4262 }
4263#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4264 else if (!err) {
4265 printk(KERN_INFO
4266 "hda_codec: Cannot set up configuration "
4267 "from BIOS. Using base mode...\n");
4268 board_config = ALC268_3ST;
4269 }
4270#endif
4271 }
4272
4273 if (board_config != ALC_MODEL_AUTO)
4274 setup_preset(codec, &alc268_presets[board_config]);
4275
4276 has_beep = 0;
4277 for (i = 0; i < spec->num_mixers; i++) {
4278 if (spec->mixers[i] == alc268_beep_mixer) {
4279 has_beep = 1;
4280 break;
4281 }
4282 }
4283
4284 if (has_beep) {
4285 err = snd_hda_attach_beep_device(codec, 0x1);
4286 if (err < 0) {
4287 alc_free(codec);
4288 return err;
4289 }
4290 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4291 /* override the amp caps for beep generator */
4292 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4293 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4294 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4295 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4296 (0 << AC_AMPCAP_MUTE_SHIFT));
4297 }
4298
Takashi Iwai60a6a842011-07-27 14:01:24 +02004299 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004300 alc_auto_fill_adc_caps(codec);
4301 alc_rebuild_imux_for_auto_mic(codec);
4302 alc_remove_invalid_adc_nids(codec);
4303 }
4304
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004305 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004306 set_capture_mixer(codec);
4307
4308 spec->vmaster_nid = 0x02;
4309
4310 codec->patch_ops = alc_patch_ops;
4311 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004312 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004313 spec->shutup = alc_eapd_shutup;
4314
4315 alc_init_jacks(codec);
4316
4317 return 0;
4318}
4319
4320/*
4321 * ALC269
4322 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004323#ifdef CONFIG_SND_HDA_POWER_SAVE
4324#define alc269_loopbacks alc880_loopbacks
4325#endif
4326
4327static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4328 .substreams = 1,
4329 .channels_min = 2,
4330 .channels_max = 8,
4331 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4332 /* NID is set in alc_build_pcms */
4333 .ops = {
4334 .open = alc_playback_pcm_open,
4335 .prepare = alc_playback_pcm_prepare,
4336 .cleanup = alc_playback_pcm_cleanup
4337 },
4338};
4339
4340static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4341 .substreams = 1,
4342 .channels_min = 2,
4343 .channels_max = 2,
4344 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4345 /* NID is set in alc_build_pcms */
4346};
4347
4348#ifdef CONFIG_SND_HDA_POWER_SAVE
4349static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4350{
4351 switch (codec->subsystem_id) {
4352 case 0x103c1586:
4353 return 1;
4354 }
4355 return 0;
4356}
4357
4358static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4359{
4360 /* update mute-LED according to the speaker mute state */
4361 if (nid == 0x01 || nid == 0x14) {
4362 int pinval;
4363 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4364 HDA_AMP_MUTE)
4365 pinval = 0x24;
4366 else
4367 pinval = 0x20;
4368 /* mic2 vref pin is used for mute LED control */
4369 snd_hda_codec_update_cache(codec, 0x19, 0,
4370 AC_VERB_SET_PIN_WIDGET_CONTROL,
4371 pinval);
4372 }
4373 return alc_check_power_status(codec, nid);
4374}
4375#endif /* CONFIG_SND_HDA_POWER_SAVE */
4376
4377/* different alc269-variants */
4378enum {
4379 ALC269_TYPE_ALC269VA,
4380 ALC269_TYPE_ALC269VB,
4381 ALC269_TYPE_ALC269VC,
4382};
4383
4384/*
4385 * BIOS auto configuration
4386 */
4387static int alc269_parse_auto_config(struct hda_codec *codec)
4388{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004389 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004390 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
4391 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4392 struct alc_spec *spec = codec->spec;
4393 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
4394 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004395
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004396 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004397}
4398
Takashi Iwai1d045db2011-07-07 18:23:21 +02004399static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4400{
4401 int val = alc_read_coef_idx(codec, 0x04);
4402 if (power_up)
4403 val |= 1 << 11;
4404 else
4405 val &= ~(1 << 11);
4406 alc_write_coef_idx(codec, 0x04, val);
4407}
4408
4409static void alc269_shutup(struct hda_codec *codec)
4410{
4411 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4412 alc269_toggle_power_output(codec, 0);
4413 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4414 alc269_toggle_power_output(codec, 0);
4415 msleep(150);
4416 }
4417}
4418
Takashi Iwai2a439522011-07-26 09:52:50 +02004419#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004420static int alc269_resume(struct hda_codec *codec)
4421{
4422 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4423 alc269_toggle_power_output(codec, 0);
4424 msleep(150);
4425 }
4426
4427 codec->patch_ops.init(codec);
4428
4429 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4430 alc269_toggle_power_output(codec, 1);
4431 msleep(200);
4432 }
4433
4434 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4435 alc269_toggle_power_output(codec, 1);
4436
4437 snd_hda_codec_resume_amp(codec);
4438 snd_hda_codec_resume_cache(codec);
4439 hda_call_check_power_status(codec, 0x01);
4440 return 0;
4441}
Takashi Iwai2a439522011-07-26 09:52:50 +02004442#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004443
4444static void alc269_fixup_hweq(struct hda_codec *codec,
4445 const struct alc_fixup *fix, int action)
4446{
4447 int coef;
4448
4449 if (action != ALC_FIXUP_ACT_INIT)
4450 return;
4451 coef = alc_read_coef_idx(codec, 0x1e);
4452 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4453}
4454
4455static void alc271_fixup_dmic(struct hda_codec *codec,
4456 const struct alc_fixup *fix, int action)
4457{
4458 static const struct hda_verb verbs[] = {
4459 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4460 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4461 {}
4462 };
4463 unsigned int cfg;
4464
4465 if (strcmp(codec->chip_name, "ALC271X"))
4466 return;
4467 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4468 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4469 snd_hda_sequence_write(codec, verbs);
4470}
4471
Takashi Iwai017f2a12011-07-09 14:42:25 +02004472static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4473 const struct alc_fixup *fix, int action)
4474{
4475 struct alc_spec *spec = codec->spec;
4476
4477 if (action != ALC_FIXUP_ACT_PROBE)
4478 return;
4479
4480 /* Due to a hardware problem on Lenovo Ideadpad, we need to
4481 * fix the sample rate of analog I/O to 44.1kHz
4482 */
4483 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
4484 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4485}
4486
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004487static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4488 const struct alc_fixup *fix, int action)
4489{
4490 int coef;
4491
4492 if (action != ALC_FIXUP_ACT_INIT)
4493 return;
4494 /* The digital-mic unit sends PDM (differential signal) instead of
4495 * the standard PCM, thus you can't record a valid mono stream as is.
4496 * Below is a workaround specific to ALC269 to control the dmic
4497 * signal source as mono.
4498 */
4499 coef = alc_read_coef_idx(codec, 0x07);
4500 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4501}
4502
Takashi Iwai1d045db2011-07-07 18:23:21 +02004503enum {
4504 ALC269_FIXUP_SONY_VAIO,
4505 ALC275_FIXUP_SONY_VAIO_GPIO2,
4506 ALC269_FIXUP_DELL_M101Z,
4507 ALC269_FIXUP_SKU_IGNORE,
4508 ALC269_FIXUP_ASUS_G73JW,
4509 ALC269_FIXUP_LENOVO_EAPD,
4510 ALC275_FIXUP_SONY_HWEQ,
4511 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004512 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004513 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004514};
4515
4516static const struct alc_fixup alc269_fixups[] = {
4517 [ALC269_FIXUP_SONY_VAIO] = {
4518 .type = ALC_FIXUP_VERBS,
4519 .v.verbs = (const struct hda_verb[]) {
4520 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4521 {}
4522 }
4523 },
4524 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4525 .type = ALC_FIXUP_VERBS,
4526 .v.verbs = (const struct hda_verb[]) {
4527 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4528 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4529 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4530 { }
4531 },
4532 .chained = true,
4533 .chain_id = ALC269_FIXUP_SONY_VAIO
4534 },
4535 [ALC269_FIXUP_DELL_M101Z] = {
4536 .type = ALC_FIXUP_VERBS,
4537 .v.verbs = (const struct hda_verb[]) {
4538 /* Enables internal speaker */
4539 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4540 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4541 {}
4542 }
4543 },
4544 [ALC269_FIXUP_SKU_IGNORE] = {
4545 .type = ALC_FIXUP_SKU,
4546 .v.sku = ALC_FIXUP_SKU_IGNORE,
4547 },
4548 [ALC269_FIXUP_ASUS_G73JW] = {
4549 .type = ALC_FIXUP_PINS,
4550 .v.pins = (const struct alc_pincfg[]) {
4551 { 0x17, 0x99130111 }, /* subwoofer */
4552 { }
4553 }
4554 },
4555 [ALC269_FIXUP_LENOVO_EAPD] = {
4556 .type = ALC_FIXUP_VERBS,
4557 .v.verbs = (const struct hda_verb[]) {
4558 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4559 {}
4560 }
4561 },
4562 [ALC275_FIXUP_SONY_HWEQ] = {
4563 .type = ALC_FIXUP_FUNC,
4564 .v.func = alc269_fixup_hweq,
4565 .chained = true,
4566 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4567 },
4568 [ALC271_FIXUP_DMIC] = {
4569 .type = ALC_FIXUP_FUNC,
4570 .v.func = alc271_fixup_dmic,
4571 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004572 [ALC269_FIXUP_PCM_44K] = {
4573 .type = ALC_FIXUP_FUNC,
4574 .v.func = alc269_fixup_pcm_44k,
4575 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004576 [ALC269_FIXUP_STEREO_DMIC] = {
4577 .type = ALC_FIXUP_FUNC,
4578 .v.func = alc269_fixup_stereo_dmic,
4579 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004580};
4581
4582static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02004583 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004584 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4585 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4586 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4587 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4588 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004589 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4590 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4591 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4592 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4593 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4594 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
4595 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4596 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4597 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4598 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4599 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02004600 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004601 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
4602 {}
4603};
4604
4605
4606static int alc269_fill_coef(struct hda_codec *codec)
4607{
4608 int val;
4609
4610 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4611 alc_write_coef_idx(codec, 0xf, 0x960b);
4612 alc_write_coef_idx(codec, 0xe, 0x8817);
4613 }
4614
4615 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4616 alc_write_coef_idx(codec, 0xf, 0x960b);
4617 alc_write_coef_idx(codec, 0xe, 0x8814);
4618 }
4619
4620 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4621 val = alc_read_coef_idx(codec, 0x04);
4622 /* Power up output pin */
4623 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4624 }
4625
4626 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4627 val = alc_read_coef_idx(codec, 0xd);
4628 if ((val & 0x0c00) >> 10 != 0x1) {
4629 /* Capless ramp up clock control */
4630 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4631 }
4632 val = alc_read_coef_idx(codec, 0x17);
4633 if ((val & 0x01c0) >> 6 != 0x4) {
4634 /* Class D power on reset */
4635 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4636 }
4637 }
4638
4639 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4640 alc_write_coef_idx(codec, 0xd, val | (1<<14));
4641
4642 val = alc_read_coef_idx(codec, 0x4); /* HP */
4643 alc_write_coef_idx(codec, 0x4, val | (1<<11));
4644
4645 return 0;
4646}
4647
4648/*
4649 */
4650#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4651#include "alc269_quirks.c"
4652#endif
4653
4654static int patch_alc269(struct hda_codec *codec)
4655{
4656 struct alc_spec *spec;
4657 int board_config, coef;
4658 int err;
4659
4660 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4661 if (spec == NULL)
4662 return -ENOMEM;
4663
4664 codec->spec = spec;
4665
4666 spec->mixer_nid = 0x0b;
4667
4668 alc_auto_parse_customize_define(codec);
4669
4670 if (codec->vendor_id == 0x10ec0269) {
4671 spec->codec_variant = ALC269_TYPE_ALC269VA;
4672 coef = alc_read_coef_idx(codec, 0);
4673 if ((coef & 0x00f0) == 0x0010) {
4674 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
4675 spec->cdefine.platform_type == 1) {
4676 alc_codec_rename(codec, "ALC271X");
4677 } else if ((coef & 0xf000) == 0x2000) {
4678 alc_codec_rename(codec, "ALC259");
4679 } else if ((coef & 0xf000) == 0x3000) {
4680 alc_codec_rename(codec, "ALC258");
4681 } else if ((coef & 0xfff0) == 0x3010) {
4682 alc_codec_rename(codec, "ALC277");
4683 } else {
4684 alc_codec_rename(codec, "ALC269VB");
4685 }
4686 spec->codec_variant = ALC269_TYPE_ALC269VB;
4687 } else if ((coef & 0x00f0) == 0x0020) {
4688 if (coef == 0xa023)
4689 alc_codec_rename(codec, "ALC259");
4690 else if (coef == 0x6023)
4691 alc_codec_rename(codec, "ALC281X");
4692 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4693 codec->bus->pci->subsystem_device == 0x21f3)
4694 alc_codec_rename(codec, "ALC3202");
4695 else
4696 alc_codec_rename(codec, "ALC269VC");
4697 spec->codec_variant = ALC269_TYPE_ALC269VC;
4698 } else
4699 alc_fix_pll_init(codec, 0x20, 0x04, 15);
4700 alc269_fill_coef(codec);
4701 }
4702
4703 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
4704 alc269_models, alc269_cfg_tbl);
4705
4706 if (board_config < 0) {
4707 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4708 codec->chip_name);
4709 board_config = ALC_MODEL_AUTO;
4710 }
4711
4712 if (board_config == ALC_MODEL_AUTO) {
4713 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
4714 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4715 }
4716
4717 if (board_config == ALC_MODEL_AUTO) {
4718 /* automatic parse from the BIOS config */
4719 err = alc269_parse_auto_config(codec);
4720 if (err < 0) {
4721 alc_free(codec);
4722 return err;
4723 }
4724#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4725 else if (!err) {
4726 printk(KERN_INFO
4727 "hda_codec: Cannot set up configuration "
4728 "from BIOS. Using base mode...\n");
4729 board_config = ALC269_BASIC;
4730 }
4731#endif
4732 }
4733
Takashi Iwai1d045db2011-07-07 18:23:21 +02004734 if (board_config != ALC_MODEL_AUTO)
4735 setup_preset(codec, &alc269_presets[board_config]);
4736
Takashi Iwai60a6a842011-07-27 14:01:24 +02004737 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004738 alc_auto_fill_adc_caps(codec);
4739 alc_rebuild_imux_for_auto_mic(codec);
4740 alc_remove_invalid_adc_nids(codec);
4741 }
4742
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004743 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004744 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004745
4746 if (!spec->no_analog && has_cdefine_beep(codec)) {
4747 err = snd_hda_attach_beep_device(codec, 0x1);
4748 if (err < 0) {
4749 alc_free(codec);
4750 return err;
4751 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004752 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004753 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004754
4755 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4756
4757 spec->vmaster_nid = 0x02;
4758
4759 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02004760#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004761 codec->patch_ops.resume = alc269_resume;
4762#endif
4763 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004764 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004765 spec->shutup = alc269_shutup;
4766
4767 alc_init_jacks(codec);
4768#ifdef CONFIG_SND_HDA_POWER_SAVE
4769 if (!spec->loopback.amplist)
4770 spec->loopback.amplist = alc269_loopbacks;
4771 if (alc269_mic2_for_mute_led(codec))
4772 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
4773#endif
4774
4775 return 0;
4776}
4777
4778/*
4779 * ALC861
4780 */
4781
Takashi Iwai1d045db2011-07-07 18:23:21 +02004782static int alc861_parse_auto_config(struct hda_codec *codec)
4783{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004784 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004785 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4786 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004787}
4788
Takashi Iwai1d045db2011-07-07 18:23:21 +02004789#ifdef CONFIG_SND_HDA_POWER_SAVE
4790static const struct hda_amp_list alc861_loopbacks[] = {
4791 { 0x15, HDA_INPUT, 0 },
4792 { 0x15, HDA_INPUT, 1 },
4793 { 0x15, HDA_INPUT, 2 },
4794 { 0x15, HDA_INPUT, 3 },
4795 { } /* end */
4796};
4797#endif
4798
4799
4800/* Pin config fixes */
4801enum {
4802 PINFIX_FSC_AMILO_PI1505,
4803};
4804
4805static const struct alc_fixup alc861_fixups[] = {
4806 [PINFIX_FSC_AMILO_PI1505] = {
4807 .type = ALC_FIXUP_PINS,
4808 .v.pins = (const struct alc_pincfg[]) {
4809 { 0x0b, 0x0221101f }, /* HP */
4810 { 0x0f, 0x90170310 }, /* speaker */
4811 { }
4812 }
4813 },
4814};
4815
4816static const struct snd_pci_quirk alc861_fixup_tbl[] = {
4817 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
4818 {}
4819};
4820
4821/*
4822 */
4823#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4824#include "alc861_quirks.c"
4825#endif
4826
4827static int patch_alc861(struct hda_codec *codec)
4828{
4829 struct alc_spec *spec;
4830 int board_config;
4831 int err;
4832
4833 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4834 if (spec == NULL)
4835 return -ENOMEM;
4836
4837 codec->spec = spec;
4838
4839 spec->mixer_nid = 0x15;
4840
4841 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
4842 alc861_models, alc861_cfg_tbl);
4843
4844 if (board_config < 0) {
4845 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4846 codec->chip_name);
4847 board_config = ALC_MODEL_AUTO;
4848 }
4849
4850 if (board_config == ALC_MODEL_AUTO) {
4851 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
4852 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4853 }
4854
4855 if (board_config == ALC_MODEL_AUTO) {
4856 /* automatic parse from the BIOS config */
4857 err = alc861_parse_auto_config(codec);
4858 if (err < 0) {
4859 alc_free(codec);
4860 return err;
4861 }
4862#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4863 else if (!err) {
4864 printk(KERN_INFO
4865 "hda_codec: Cannot set up configuration "
4866 "from BIOS. Using base mode...\n");
4867 board_config = ALC861_3ST_DIG;
4868 }
4869#endif
4870 }
4871
Takashi Iwai1d045db2011-07-07 18:23:21 +02004872 if (board_config != ALC_MODEL_AUTO)
4873 setup_preset(codec, &alc861_presets[board_config]);
4874
Takashi Iwai60a6a842011-07-27 14:01:24 +02004875 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004876 alc_auto_fill_adc_caps(codec);
4877 alc_rebuild_imux_for_auto_mic(codec);
4878 alc_remove_invalid_adc_nids(codec);
4879 }
4880
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004881 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004882 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004883
4884 if (!spec->no_analog) {
4885 err = snd_hda_attach_beep_device(codec, 0x23);
4886 if (err < 0) {
4887 alc_free(codec);
4888 return err;
4889 }
4890 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
4891 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004892
4893 spec->vmaster_nid = 0x03;
4894
4895 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4896
4897 codec->patch_ops = alc_patch_ops;
4898 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02004899 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004900#ifdef CONFIG_SND_HDA_POWER_SAVE
4901 spec->power_hook = alc_power_eapd;
4902#endif
4903 }
4904#ifdef CONFIG_SND_HDA_POWER_SAVE
4905 if (!spec->loopback.amplist)
4906 spec->loopback.amplist = alc861_loopbacks;
4907#endif
4908
4909 return 0;
4910}
4911
4912/*
4913 * ALC861-VD support
4914 *
4915 * Based on ALC882
4916 *
4917 * In addition, an independent DAC
4918 */
4919#ifdef CONFIG_SND_HDA_POWER_SAVE
4920#define alc861vd_loopbacks alc880_loopbacks
4921#endif
4922
Takashi Iwai1d045db2011-07-07 18:23:21 +02004923static int alc861vd_parse_auto_config(struct hda_codec *codec)
4924{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004925 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004926 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4927 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004928}
4929
Takashi Iwai1d045db2011-07-07 18:23:21 +02004930enum {
4931 ALC660VD_FIX_ASUS_GPIO1
4932};
4933
4934/* reset GPIO1 */
4935static const struct alc_fixup alc861vd_fixups[] = {
4936 [ALC660VD_FIX_ASUS_GPIO1] = {
4937 .type = ALC_FIXUP_VERBS,
4938 .v.verbs = (const struct hda_verb[]) {
4939 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
4940 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4941 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4942 { }
4943 }
4944 },
4945};
4946
4947static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
4948 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
4949 {}
4950};
4951
4952static const struct hda_verb alc660vd_eapd_verbs[] = {
4953 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
4954 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
4955 { }
4956};
4957
4958/*
4959 */
4960#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4961#include "alc861vd_quirks.c"
4962#endif
4963
4964static int patch_alc861vd(struct hda_codec *codec)
4965{
4966 struct alc_spec *spec;
4967 int err, board_config;
4968
4969 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4970 if (spec == NULL)
4971 return -ENOMEM;
4972
4973 codec->spec = spec;
4974
4975 spec->mixer_nid = 0x0b;
4976
4977 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
4978 alc861vd_models, alc861vd_cfg_tbl);
4979
4980 if (board_config < 0) {
4981 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4982 codec->chip_name);
4983 board_config = ALC_MODEL_AUTO;
4984 }
4985
4986 if (board_config == ALC_MODEL_AUTO) {
4987 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
4988 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4989 }
4990
4991 if (board_config == ALC_MODEL_AUTO) {
4992 /* automatic parse from the BIOS config */
4993 err = alc861vd_parse_auto_config(codec);
4994 if (err < 0) {
4995 alc_free(codec);
4996 return err;
4997 }
4998#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4999 else if (!err) {
5000 printk(KERN_INFO
5001 "hda_codec: Cannot set up configuration "
5002 "from BIOS. Using base mode...\n");
5003 board_config = ALC861VD_3ST;
5004 }
5005#endif
5006 }
5007
Takashi Iwai1d045db2011-07-07 18:23:21 +02005008 if (board_config != ALC_MODEL_AUTO)
5009 setup_preset(codec, &alc861vd_presets[board_config]);
5010
5011 if (codec->vendor_id == 0x10ec0660) {
5012 /* always turn on EAPD */
5013 add_verb(spec, alc660vd_eapd_verbs);
5014 }
5015
Takashi Iwai60a6a842011-07-27 14:01:24 +02005016 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005017 alc_auto_fill_adc_caps(codec);
5018 alc_rebuild_imux_for_auto_mic(codec);
5019 alc_remove_invalid_adc_nids(codec);
5020 }
5021
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005022 if (!spec->no_analog && !spec->cap_mixer)
5023 set_capture_mixer(codec);
5024
5025 if (!spec->no_analog) {
5026 err = snd_hda_attach_beep_device(codec, 0x23);
5027 if (err < 0) {
5028 alc_free(codec);
5029 return err;
5030 }
5031 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5032 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005033
5034 spec->vmaster_nid = 0x02;
5035
5036 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5037
5038 codec->patch_ops = alc_patch_ops;
5039
5040 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005041 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005042 spec->shutup = alc_eapd_shutup;
5043#ifdef CONFIG_SND_HDA_POWER_SAVE
5044 if (!spec->loopback.amplist)
5045 spec->loopback.amplist = alc861vd_loopbacks;
5046#endif
5047
5048 return 0;
5049}
5050
5051/*
5052 * ALC662 support
5053 *
5054 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5055 * configuration. Each pin widget can choose any input DACs and a mixer.
5056 * Each ADC is connected from a mixer of all inputs. This makes possible
5057 * 6-channel independent captures.
5058 *
5059 * In addition, an independent DAC for the multi-playback (not used in this
5060 * driver yet).
5061 */
5062#ifdef CONFIG_SND_HDA_POWER_SAVE
5063#define alc662_loopbacks alc880_loopbacks
5064#endif
5065
5066/*
5067 * BIOS auto configuration
5068 */
5069
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005070static int alc662_parse_auto_config(struct hda_codec *codec)
5071{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005072 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005073 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5074 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5075 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005076
Kailang Yang6227cdc2010-02-25 08:36:52 +01005077 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5078 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005079 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005080 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005081 ssids = alc662_ssids;
5082 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005083}
5084
Todd Broch6be79482010-12-07 16:51:05 -08005085static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005086 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005087{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005088 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005089 return;
Todd Broch6be79482010-12-07 16:51:05 -08005090 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5091 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5092 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5093 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5094 (0 << AC_AMPCAP_MUTE_SHIFT)))
5095 printk(KERN_WARNING
5096 "hda_codec: failed to override amp caps for NID 0x2\n");
5097}
5098
David Henningsson6cb3b702010-09-09 08:51:44 +02005099enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005100 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005101 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005102 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005103 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005104 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005105 ALC662_FIXUP_HP_RP5800,
David Henningsson6cb3b702010-09-09 08:51:44 +02005106};
5107
5108static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005109 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005110 .type = ALC_FIXUP_PINS,
5111 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005112 { 0x15, 0x99130112 }, /* subwoofer */
5113 { }
5114 }
5115 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005116 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005117 .type = ALC_FIXUP_PINS,
5118 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005119 { 0x17, 0x99130112 }, /* subwoofer */
5120 { }
5121 }
5122 },
Todd Broch6be79482010-12-07 16:51:05 -08005123 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005124 .type = ALC_FIXUP_FUNC,
5125 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005126 },
5127 [ALC662_FIXUP_CZC_P10T] = {
5128 .type = ALC_FIXUP_VERBS,
5129 .v.verbs = (const struct hda_verb[]) {
5130 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5131 {}
5132 }
5133 },
David Henningsson94024cd2011-04-29 14:10:55 +02005134 [ALC662_FIXUP_SKU_IGNORE] = {
5135 .type = ALC_FIXUP_SKU,
5136 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005137 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005138 [ALC662_FIXUP_HP_RP5800] = {
5139 .type = ALC_FIXUP_PINS,
5140 .v.pins = (const struct alc_pincfg[]) {
5141 { 0x14, 0x0221201f }, /* HP out */
5142 { }
5143 },
5144 .chained = true,
5145 .chain_id = ALC662_FIXUP_SKU_IGNORE
5146 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005147};
5148
Takashi Iwaia9111322011-05-02 11:30:18 +02005149static const struct snd_pci_quirk alc662_fixup_tbl[] = {
David Henningssona6c47a82011-02-10 15:39:19 +01005150 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005151 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005152 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005153 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005154 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005155 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005156 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005157 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02005158 {}
5159};
5160
Todd Broch6be79482010-12-07 16:51:05 -08005161static const struct alc_model_fixup alc662_fixup_models[] = {
5162 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
5163 {}
5164};
David Henningsson6cb3b702010-09-09 08:51:44 +02005165
5166
Takashi Iwai1d045db2011-07-07 18:23:21 +02005167/*
5168 */
5169#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5170#include "alc662_quirks.c"
5171#endif
5172
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005173static int patch_alc662(struct hda_codec *codec)
5174{
5175 struct alc_spec *spec;
5176 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02005177 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005178
5179 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5180 if (!spec)
5181 return -ENOMEM;
5182
5183 codec->spec = spec;
5184
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005185 spec->mixer_nid = 0x0b;
5186
Kailang Yangda00c242010-03-19 11:23:45 +01005187 alc_auto_parse_customize_define(codec);
5188
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005189 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5190
Kailang Yang693194f2010-10-21 08:51:48 +02005191 coef = alc_read_coef_idx(codec, 0);
5192 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005193 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005194 else if (coef & (1 << 14) &&
5195 codec->bus->pci->subsystem_vendor == 0x1025 &&
5196 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005197 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005198 else if (coef == 0x4011)
5199 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005200
Takashi Iwai1d045db2011-07-07 18:23:21 +02005201 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
5202 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005203 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005204 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5205 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005206 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005207 }
5208
Takashi Iwai1d045db2011-07-07 18:23:21 +02005209 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005210 alc_pick_fixup(codec, alc662_fixup_models,
5211 alc662_fixup_tbl, alc662_fixups);
5212 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005213 /* automatic parse from the BIOS config */
5214 err = alc662_parse_auto_config(codec);
5215 if (err < 0) {
5216 alc_free(codec);
5217 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005218 }
5219#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5220 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005221 printk(KERN_INFO
5222 "hda_codec: Cannot set up configuration "
5223 "from BIOS. Using base mode...\n");
5224 board_config = ALC662_3ST_2ch_DIG;
5225 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005226#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005227 }
5228
Takashi Iwai1d045db2011-07-07 18:23:21 +02005229 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005230 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005231
Takashi Iwai60a6a842011-07-27 14:01:24 +02005232 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005233 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005234 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005235 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005236 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005237
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005238 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005239 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005240
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005241 if (!spec->no_analog && has_cdefine_beep(codec)) {
5242 err = snd_hda_attach_beep_device(codec, 0x1);
5243 if (err < 0) {
5244 alc_free(codec);
5245 return err;
5246 }
Kailang Yangda00c242010-03-19 11:23:45 +01005247 switch (codec->vendor_id) {
5248 case 0x10ec0662:
5249 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5250 break;
5251 case 0x10ec0272:
5252 case 0x10ec0663:
5253 case 0x10ec0665:
5254 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5255 break;
5256 case 0x10ec0273:
5257 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5258 break;
5259 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005260 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005261 spec->vmaster_nid = 0x02;
5262
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005263 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5264
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005265 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005266 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005267 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c716152011-04-07 10:37:16 +02005268 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005269
Kailang Yangbf1b0222010-10-21 08:49:56 +02005270 alc_init_jacks(codec);
5271
Takashi Iwaicb53c622007-08-10 17:21:45 +02005272#ifdef CONFIG_SND_HDA_POWER_SAVE
5273 if (!spec->loopback.amplist)
5274 spec->loopback.amplist = alc662_loopbacks;
5275#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005276
5277 return 0;
5278}
5279
Kailang Yang274693f2009-12-03 10:07:50 +01005280static int patch_alc888(struct hda_codec *codec)
5281{
5282 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5283 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005284 if (codec->vendor_id == 0x10ec0887)
5285 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5286 else
5287 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005288 if (!codec->chip_name) {
5289 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005290 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005291 }
5292 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005293 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005294 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005295}
5296
Kailang Yangb478b992011-05-18 11:51:15 +02005297static int patch_alc899(struct hda_codec *codec)
5298{
5299 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5300 kfree(codec->chip_name);
5301 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5302 }
5303 return patch_alc882(codec);
5304}
5305
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005306/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005307 * ALC680 support
5308 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005309
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005310static int alc680_parse_auto_config(struct hda_codec *codec)
5311{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005312 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005313}
5314
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005315/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005316 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005317static int patch_alc680(struct hda_codec *codec)
5318{
5319 struct alc_spec *spec;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005320 int err;
5321
5322 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5323 if (spec == NULL)
5324 return -ENOMEM;
5325
5326 codec->spec = spec;
5327
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005328 /* ALC680 has no aa-loopback mixer */
5329
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02005330 /* automatic parse from the BIOS config */
5331 err = alc680_parse_auto_config(codec);
5332 if (err < 0) {
5333 alc_free(codec);
5334 return err;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005335 }
5336
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005337 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005338 set_capture_mixer(codec);
5339
5340 spec->vmaster_nid = 0x02;
5341
5342 codec->patch_ops = alc_patch_ops;
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02005343 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005344
5345 return 0;
5346}
5347
5348/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349 * patch entries
5350 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005351static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005352 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005354 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005355 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005356 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005357 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005358 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005359 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005360 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005361 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005362 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005363 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005364 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5365 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5366 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005367 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005368 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005369 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5370 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005371 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005372 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005373 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005374 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005375 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02005377 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005378 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005379 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005380 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005381 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005382 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005383 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005384 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005385 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005386 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02005387 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005388 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005389 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 {} /* terminator */
5391};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005392
5393MODULE_ALIAS("snd-hda-codec-id:10ec*");
5394
5395MODULE_LICENSE("GPL");
5396MODULE_DESCRIPTION("Realtek HD-audio codec");
5397
5398static struct hda_codec_preset_list realtek_list = {
5399 .preset = snd_hda_preset_realtek,
5400 .owner = THIS_MODULE,
5401};
5402
5403static int __init patch_realtek_init(void)
5404{
5405 return snd_hda_add_codec_preset(&realtek_list);
5406}
5407
5408static void __exit patch_realtek_exit(void)
5409{
5410 snd_hda_delete_codec_preset(&realtek_list);
5411}
5412
5413module_init(patch_realtek_init)
5414module_exit(patch_realtek_exit)