blob: 0503c999e7d361290ac99945dc4eef7509ca0ed3 [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 */
Takashi Iwai8974bd512011-09-19 11:31:34 +0200171 unsigned int automute_lines:1; /* automute line-out as well; NOP when automute_hp_lo isn't set */
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200172 unsigned int automute_hp_lo:1; /* both HP and LO available */
Takashi Iwaicb53c622007-08-10 17:21:45 +0200173
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100174 /* other flags */
175 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai21268962011-07-07 15:01:13 +0200176 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai584c0c42011-03-10 12:51:11 +0100177 unsigned int single_input_src:1;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +0200178 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
Takashi Iwaid922b512011-04-28 12:18:53 +0200179
180 /* auto-mute control */
181 int automute_mode;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200182 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
Takashi Iwaid922b512011-04-28 12:18:53 +0200183
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200184 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200185 int codec_variant; /* flag for other variants */
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100186
Takashi Iwai2134ea42008-01-10 16:53:55 +0100187 /* for virtual master */
188 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200189#ifdef CONFIG_SND_HDA_POWER_SAVE
190 struct hda_loopback_check loopback;
191#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200192
193 /* for PLL fix */
194 hda_nid_t pll_nid;
195 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +0100196
197 /* fix-up list */
198 int fixup_id;
199 const struct alc_fixup *fixup_list;
200 const char *fixup_name;
Takashi Iwaice764ab2011-04-27 16:35:23 +0200201
202 /* multi-io */
203 int multi_ios;
204 struct alc_multi_io multi_io[4];
Kailang Yangdf694da2005-12-05 19:42:22 +0100205};
206
Takashi Iwai1d045db2011-07-07 18:23:21 +0200207#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Takashi Iwai44c02402011-07-08 15:14:19 +0200209static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
210 int dir, unsigned int bits)
211{
212 if (!nid)
213 return false;
214 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
215 if (query_amp_caps(codec, nid, dir) & bits)
216 return true;
217 return false;
218}
219
220#define nid_has_mute(codec, nid, dir) \
221 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
222#define nid_has_volume(codec, nid, dir) \
223 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225/*
226 * input MUX handling
227 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200228static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
229 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230{
231 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
232 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200233 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
234 if (mux_idx >= spec->num_mux_defs)
235 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100236 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
237 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200238 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200241static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
244 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
245 struct alc_spec *spec = codec->spec;
246 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
247
248 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
249 return 0;
250}
251
Takashi Iwai21268962011-07-07 15:01:13 +0200252static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253{
Takashi Iwai21268962011-07-07 15:01:13 +0200254 struct alc_spec *spec = codec->spec;
255 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
256
257 if (spec->cur_adc && spec->cur_adc != new_adc) {
258 /* stream is running, let's swap the current ADC */
259 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
260 spec->cur_adc = new_adc;
261 snd_hda_codec_setup_stream(codec, new_adc,
262 spec->cur_adc_stream_tag, 0,
263 spec->cur_adc_format);
264 return true;
265 }
266 return false;
267}
268
269/* select the given imux item; either unmute exclusively or select the route */
270static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
271 unsigned int idx, bool force)
272{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100274 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100275 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200276 int i, type;
277 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Takashi Iwaicd896c32008-11-18 12:36:33 +0100279 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
280 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100281 if (!imux->num_items && mux_idx > 0)
282 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100283
Takashi Iwai21268962011-07-07 15:01:13 +0200284 if (idx >= imux->num_items)
285 idx = imux->num_items - 1;
286 if (spec->cur_mux[adc_idx] == idx && !force)
287 return 0;
288 spec->cur_mux[adc_idx] = idx;
289
290 if (spec->dyn_adc_switch) {
291 alc_dyn_adc_pcm_resetup(codec, idx);
292 adc_idx = spec->dyn_adc_idx[idx];
293 }
294
295 nid = spec->capsrc_nids ?
296 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
297
298 /* no selection? */
299 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
300 return 1;
301
Takashi Iwaia22d5432009-07-27 12:54:26 +0200302 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200303 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100304 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100305 for (i = 0; i < imux->num_items; i++) {
306 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
307 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
308 imux->items[i].index,
309 HDA_AMP_MUTE, v);
310 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100311 } else {
312 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200313 snd_hda_codec_write_cache(codec, nid, 0,
314 AC_VERB_SET_CONNECT_SEL,
315 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100316 }
Takashi Iwai21268962011-07-07 15:01:13 +0200317 return 1;
318}
319
320static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
321 struct snd_ctl_elem_value *ucontrol)
322{
323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
324 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
325 return alc_mux_select(codec, adc_idx,
326 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100327}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100330 * set up the input pin config (depending on the given auto-pin type)
331 */
332static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
333 int auto_pin_type)
334{
335 unsigned int val = PIN_IN;
336
Takashi Iwai86e29592010-09-09 14:50:17 +0200337 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100338 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200339 unsigned int oldval;
340 oldval = snd_hda_codec_read(codec, nid, 0,
341 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100342 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100343 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200344 /* if the default pin setup is vref50, we give it priority */
345 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100346 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200347 else if (pincap & AC_PINCAP_VREF_50)
348 val = PIN_VREF50;
349 else if (pincap & AC_PINCAP_VREF_100)
350 val = PIN_VREF100;
351 else if (pincap & AC_PINCAP_VREF_GRD)
352 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100353 }
354 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
355}
356
357/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200358 * Append the given mixer and verb elements for the later use
359 * The mixer array is referred in build_controls(), and init_verbs are
360 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100361 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200362static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100363{
364 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
365 return;
366 spec->mixers[spec->num_mixers++] = mix;
367}
368
369static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
370{
371 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
372 return;
373 spec->init_verbs[spec->num_init_verbs++] = verb;
374}
375
376/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200377 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100378 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200379/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200380static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200381 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
382 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
383 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
384 { }
385};
386
Takashi Iwaia9111322011-05-02 11:30:18 +0200387static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200388 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
389 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
390 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
391 { }
392};
393
Takashi Iwaia9111322011-05-02 11:30:18 +0200394static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200395 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
396 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
397 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
398 { }
399};
400
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200401/*
402 * Fix hardware PLL issue
403 * On some codecs, the analog PLL gating control must be off while
404 * the default value is 1.
405 */
406static void alc_fix_pll(struct hda_codec *codec)
407{
408 struct alc_spec *spec = codec->spec;
409 unsigned int val;
410
411 if (!spec->pll_nid)
412 return;
413 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
414 spec->pll_coef_idx);
415 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
416 AC_VERB_GET_PROC_COEF, 0);
417 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
418 spec->pll_coef_idx);
419 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
420 val & ~(1 << spec->pll_coef_bit));
421}
422
423static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
424 unsigned int coef_idx, unsigned int coef_bit)
425{
426 struct alc_spec *spec = codec->spec;
427 spec->pll_nid = nid;
428 spec->pll_coef_idx = coef_idx;
429 spec->pll_coef_bit = coef_bit;
430 alc_fix_pll(codec);
431}
432
Takashi Iwai1d045db2011-07-07 18:23:21 +0200433/*
434 * Jack-reporting via input-jack layer
435 */
436
437/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200438static int alc_init_jacks(struct hda_codec *codec)
439{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100440#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200441 struct alc_spec *spec = codec->spec;
442 int err;
443 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200444 unsigned int mic_nid = spec->ext_mic_pin;
445 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200446
Takashi Iwai265a0242010-09-21 11:26:21 +0200447 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100448 err = snd_hda_input_jack_add(codec, hp_nid,
449 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200450 if (err < 0)
451 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100452 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200453 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200454
Takashi Iwai265a0242010-09-21 11:26:21 +0200455 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100456 err = snd_hda_input_jack_add(codec, mic_nid,
457 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200458 if (err < 0)
459 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100460 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200461 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200462 if (dock_nid) {
463 err = snd_hda_input_jack_add(codec, dock_nid,
464 SND_JACK_MICROPHONE, NULL);
465 if (err < 0)
466 return err;
467 snd_hda_input_jack_report(codec, dock_nid);
468 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100469#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200470 return 0;
471}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200472
Takashi Iwai1d045db2011-07-07 18:23:21 +0200473/*
474 * Jack detections for HP auto-mute and mic-switch
475 */
476
477/* check each pin in the given array; returns true if any of them is plugged */
478static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200479{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200480 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200481
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200482 for (i = 0; i < num_pins; i++) {
483 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200484 if (!nid)
485 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100486 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200487 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200488 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200489 return present;
490}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200491
Takashi Iwai1d045db2011-07-07 18:23:21 +0200492/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200493static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200494 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200495{
496 struct alc_spec *spec = codec->spec;
497 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200498 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200499 int i;
500
501 for (i = 0; i < num_pins; i++) {
502 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200503 if (!nid)
504 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200505 switch (spec->automute_mode) {
506 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200507 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200508 AC_VERB_SET_PIN_WIDGET_CONTROL,
509 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200510 break;
511 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200512 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200513 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200514 break;
515 case ALC_AUTOMUTE_MIXER:
516 nid = spec->automute_mixer_nid[i];
517 if (!nid)
518 break;
519 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200520 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200521 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200522 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200523 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200524 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200525 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200526}
527
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200528/* Toggle internal speakers muting */
529static void update_speakers(struct hda_codec *codec)
530{
531 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200532 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200533
Takashi Iwaic0a20262011-06-10 15:28:15 +0200534 /* Control HP pins/amps depending on master_mute state;
535 * in general, HP pins/amps control should be enabled in all cases,
536 * but currently set only for master_mute, just to be safe
537 */
538 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
539 spec->autocfg.hp_pins, spec->master_mute, true);
540
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200541 if (!spec->automute)
542 on = 0;
543 else
544 on = spec->jack_present | spec->line_jack_present;
545 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200546 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200547 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200548
549 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200550 /* if LO is a copy of either HP or Speaker, don't need to handle it */
551 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
552 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200553 return;
Takashi Iwai8974bd512011-09-19 11:31:34 +0200554 if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200555 on = 0;
556 else
557 on = spec->jack_present;
558 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200559 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200560 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200561}
562
Takashi Iwai1d045db2011-07-07 18:23:21 +0200563/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200564static void alc_hp_automute(struct hda_codec *codec)
565{
566 struct alc_spec *spec = codec->spec;
567
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200568 spec->jack_present =
569 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
570 spec->autocfg.hp_pins);
Takashi Iwai3c715a92011-08-23 12:41:09 +0200571 if (!spec->automute)
572 return;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200573 update_speakers(codec);
574}
575
Takashi Iwai1d045db2011-07-07 18:23:21 +0200576/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200577static void alc_line_automute(struct hda_codec *codec)
578{
579 struct alc_spec *spec = codec->spec;
580
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200581 spec->line_jack_present =
582 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
583 spec->autocfg.line_out_pins);
Takashi Iwai3c715a92011-08-23 12:41:09 +0200584 if (!spec->automute || !spec->detect_line)
585 return;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200586 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;
Takashi Iwai8974bd512011-09-19 11:31:34 +0200806 else if (!spec->automute_hp_lo || !spec->automute_lines)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200807 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:
Takashi Iwai8974bd512011-09-19 11:31:34 +0200827 if (spec->automute &&
828 (!spec->automute_hp_lo || !spec->automute_lines))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200829 return 0;
830 spec->automute = 1;
831 spec->automute_lines = 0;
832 break;
833 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200834 if (!spec->automute_hp_lo)
835 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200836 if (spec->automute && spec->automute_lines)
837 return 0;
838 spec->automute = 1;
839 spec->automute_lines = 1;
840 break;
841 default:
842 return -EINVAL;
843 }
844 update_speakers(codec);
845 return 1;
846}
847
Takashi Iwaia9111322011-05-02 11:30:18 +0200848static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200849 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
850 .name = "Auto-Mute Mode",
851 .info = alc_automute_mode_info,
852 .get = alc_automute_mode_get,
853 .put = alc_automute_mode_put,
854};
855
Takashi Iwai1d045db2011-07-07 18:23:21 +0200856static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
857{
858 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
859 return snd_array_new(&spec->kctls);
860}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200861
862static int alc_add_automute_mode_enum(struct hda_codec *codec)
863{
864 struct alc_spec *spec = codec->spec;
865 struct snd_kcontrol_new *knew;
866
867 knew = alc_kcontrol_new(spec);
868 if (!knew)
869 return -ENOMEM;
870 *knew = alc_automute_mode_enum;
871 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
872 if (!knew->name)
873 return -ENOMEM;
874 return 0;
875}
876
Takashi Iwai1d045db2011-07-07 18:23:21 +0200877/*
878 * Check the availability of HP/line-out auto-mute;
879 * Set up appropriately if really supported
880 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200881static void alc_init_auto_hp(struct hda_codec *codec)
882{
883 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200884 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200885 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200886 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200887
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200888 if (cfg->hp_pins[0])
889 present++;
890 if (cfg->line_out_pins[0])
891 present++;
892 if (cfg->speaker_pins[0])
893 present++;
894 if (present < 2) /* need two different output types */
895 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200896 if (present == 3)
897 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200898
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200899 if (!cfg->speaker_pins[0] &&
900 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200901 memcpy(cfg->speaker_pins, cfg->line_out_pins,
902 sizeof(cfg->speaker_pins));
903 cfg->speaker_outs = cfg->line_outs;
904 }
905
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200906 if (!cfg->hp_pins[0] &&
907 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200908 memcpy(cfg->hp_pins, cfg->line_out_pins,
909 sizeof(cfg->hp_pins));
910 cfg->hp_outs = cfg->line_outs;
911 }
912
913 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200914 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200915 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200916 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200917 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200918 nid);
919 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200920 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200921 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200922 spec->automute = 1;
923 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200924 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200925 if (spec->automute && cfg->line_out_pins[0] &&
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200926 cfg->speaker_pins[0] &&
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200927 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
928 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
929 for (i = 0; i < cfg->line_outs; i++) {
930 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200931 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200932 continue;
933 snd_printdd("realtek: Enable Line-Out auto-muting "
934 "on NID 0x%x\n", nid);
935 snd_hda_codec_write_cache(codec, nid, 0,
936 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200937 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200938 spec->detect_line = 1;
939 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200940 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200941 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200942
943 if (spec->automute) {
944 /* create a control for automute mode */
945 alc_add_automute_mode_enum(codec);
946 spec->unsol_event = alc_sku_unsol_event;
947 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200948}
949
Takashi Iwai1d045db2011-07-07 18:23:21 +0200950/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200951static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
952{
953 int i;
954 for (i = 0; i < nums; i++)
955 if (list[i] == nid)
956 return i;
957 return -1;
958}
959
Takashi Iwai1d045db2011-07-07 18:23:21 +0200960/* check whether dynamic ADC-switching is available */
961static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
962{
963 struct alc_spec *spec = codec->spec;
964 struct hda_input_mux *imux = &spec->private_imux[0];
965 int i, n, idx;
966 hda_nid_t cap, pin;
967
968 if (imux != spec->input_mux) /* no dynamic imux? */
969 return false;
970
971 for (n = 0; n < spec->num_adc_nids; n++) {
972 cap = spec->private_capsrc_nids[n];
973 for (i = 0; i < imux->num_items; i++) {
974 pin = spec->imux_pins[i];
975 if (!pin)
976 return false;
977 if (get_connection_index(codec, cap, pin) < 0)
978 break;
979 }
980 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +0200981 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +0200982 }
983
984 for (i = 0; i < imux->num_items; i++) {
985 pin = spec->imux_pins[i];
986 for (n = 0; n < spec->num_adc_nids; n++) {
987 cap = spec->private_capsrc_nids[n];
988 idx = get_connection_index(codec, cap, pin);
989 if (idx >= 0) {
990 imux->items[i].index = idx;
991 spec->dyn_adc_idx[i] = n;
992 break;
993 }
994 }
995 }
996
997 snd_printdd("realtek: enabling ADC switching\n");
998 spec->dyn_adc_switch = 1;
999 return true;
1000}
Takashi Iwai21268962011-07-07 15:01:13 +02001001
1002/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1003static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1004{
1005 struct alc_spec *spec = codec->spec;
1006 struct hda_input_mux *imux;
1007 static char * const texts[3] = {
1008 "Mic", "Internal Mic", "Dock Mic"
1009 };
1010 int i;
1011
1012 if (!spec->auto_mic)
1013 return false;
1014 imux = &spec->private_imux[0];
1015 if (spec->input_mux == imux)
1016 return true;
1017 spec->imux_pins[0] = spec->ext_mic_pin;
1018 spec->imux_pins[1] = spec->int_mic_pin;
1019 spec->imux_pins[2] = spec->dock_mic_pin;
1020 for (i = 0; i < 3; i++) {
1021 strcpy(imux->items[i].label, texts[i]);
1022 if (spec->imux_pins[i])
1023 imux->num_items = i + 1;
1024 }
1025 spec->num_mux_defs = 1;
1026 spec->input_mux = imux;
1027 return true;
1028}
1029
1030/* check whether all auto-mic pins are valid; setup indices if OK */
1031static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1032{
1033 struct alc_spec *spec = codec->spec;
1034 const struct hda_input_mux *imux;
1035
1036 if (!spec->auto_mic)
1037 return false;
1038 if (spec->auto_mic_valid_imux)
1039 return true; /* already checked */
1040
1041 /* fill up imux indices */
1042 if (!alc_check_dyn_adc_switch(codec)) {
1043 spec->auto_mic = 0;
1044 return false;
1045 }
1046
1047 imux = spec->input_mux;
1048 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1049 spec->imux_pins, imux->num_items);
1050 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1051 spec->imux_pins, imux->num_items);
1052 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1053 spec->imux_pins, imux->num_items);
1054 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1055 spec->auto_mic = 0;
1056 return false; /* no corresponding imux */
1057 }
1058
1059 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1060 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001061 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001062 if (spec->dock_mic_pin)
1063 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1064 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001065 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001066
1067 spec->auto_mic_valid_imux = 1;
1068 spec->auto_mic = 1;
1069 return true;
1070}
1071
Takashi Iwai1d045db2011-07-07 18:23:21 +02001072/*
1073 * Check the availability of auto-mic switch;
1074 * Set up if really supported
1075 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001076static void alc_init_auto_mic(struct hda_codec *codec)
1077{
1078 struct alc_spec *spec = codec->spec;
1079 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001080 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001081 int i;
1082
Takashi Iwai21268962011-07-07 15:01:13 +02001083 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1084
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001085 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001086 for (i = 0; i < cfg->num_inputs; i++) {
1087 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001088 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001089 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001090 switch (snd_hda_get_input_pin_attr(defcfg)) {
1091 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001092 if (fixed)
1093 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001094 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1095 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001096 fixed = nid;
1097 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001098 case INPUT_PIN_ATTR_UNUSED:
1099 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001100 case INPUT_PIN_ATTR_DOCK:
1101 if (dock)
1102 return; /* already occupied */
1103 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1104 return; /* invalid type */
1105 dock = nid;
1106 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001107 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001108 if (ext)
1109 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001110 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1111 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001112 ext = nid;
1113 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001114 }
1115 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001116 if (!ext && dock) {
1117 ext = dock;
1118 dock = 0;
1119 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001120 if (!ext || !fixed)
1121 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001122 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001123 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001124 if (dock && !is_jack_detectable(codec, dock))
1125 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001126
1127 /* check imux indices */
1128 spec->ext_mic_pin = ext;
1129 spec->int_mic_pin = fixed;
1130 spec->dock_mic_pin = dock;
1131
1132 spec->auto_mic = 1;
1133 if (!alc_auto_mic_check_imux(codec))
1134 return;
1135
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001136 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1137 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001138 spec->unsol_event = alc_sku_unsol_event;
1139}
1140
Takashi Iwai1d045db2011-07-07 18:23:21 +02001141/* check the availabilities of auto-mute and auto-mic switches */
1142static void alc_auto_check_switches(struct hda_codec *codec)
1143{
1144 alc_init_auto_hp(codec);
1145 alc_init_auto_mic(codec);
1146}
1147
1148/*
1149 * Realtek SSID verification
1150 */
1151
David Henningsson90622912010-10-14 14:50:18 +02001152/* Could be any non-zero and even value. When used as fixup, tells
1153 * the driver to ignore any present sku defines.
1154 */
1155#define ALC_FIXUP_SKU_IGNORE (2)
1156
Kailang Yangda00c242010-03-19 11:23:45 +01001157static int alc_auto_parse_customize_define(struct hda_codec *codec)
1158{
1159 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001160 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001161 struct alc_spec *spec = codec->spec;
1162
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001163 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1164
David Henningsson90622912010-10-14 14:50:18 +02001165 if (spec->cdefine.fixup) {
1166 ass = spec->cdefine.sku_cfg;
1167 if (ass == ALC_FIXUP_SKU_IGNORE)
1168 return -1;
1169 goto do_sku;
1170 }
1171
Kailang Yangda00c242010-03-19 11:23:45 +01001172 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001173 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001174 goto do_sku;
1175
1176 nid = 0x1d;
1177 if (codec->vendor_id == 0x10ec0260)
1178 nid = 0x17;
1179 ass = snd_hda_codec_get_pincfg(codec, nid);
1180
1181 if (!(ass & 1)) {
1182 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1183 codec->chip_name, ass);
1184 return -1;
1185 }
1186
1187 /* check sum */
1188 tmp = 0;
1189 for (i = 1; i < 16; i++) {
1190 if ((ass >> i) & 1)
1191 tmp++;
1192 }
1193 if (((ass >> 16) & 0xf) != tmp)
1194 return -1;
1195
1196 spec->cdefine.port_connectivity = ass >> 30;
1197 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1198 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1199 spec->cdefine.customization = ass >> 8;
1200do_sku:
1201 spec->cdefine.sku_cfg = ass;
1202 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1203 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1204 spec->cdefine.swap = (ass & 0x2) >> 1;
1205 spec->cdefine.override = ass & 0x1;
1206
1207 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1208 nid, spec->cdefine.sku_cfg);
1209 snd_printd("SKU: port_connectivity=0x%x\n",
1210 spec->cdefine.port_connectivity);
1211 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1212 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1213 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1214 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1215 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1216 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1217 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1218
1219 return 0;
1220}
1221
Takashi Iwai1d045db2011-07-07 18:23:21 +02001222/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001223static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1224{
Takashi Iwai21268962011-07-07 15:01:13 +02001225 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001226}
1227
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001228/* check subsystem ID and set up device-specific initialization;
1229 * return 1 if initialized, 0 if invalid SSID
1230 */
1231/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1232 * 31 ~ 16 : Manufacture ID
1233 * 15 ~ 8 : SKU ID
1234 * 7 ~ 0 : Assembly ID
1235 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1236 */
1237static int alc_subsystem_id(struct hda_codec *codec,
1238 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001239 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001240{
1241 unsigned int ass, tmp, i;
1242 unsigned nid;
1243 struct alc_spec *spec = codec->spec;
1244
David Henningsson90622912010-10-14 14:50:18 +02001245 if (spec->cdefine.fixup) {
1246 ass = spec->cdefine.sku_cfg;
1247 if (ass == ALC_FIXUP_SKU_IGNORE)
1248 return 0;
1249 goto do_sku;
1250 }
1251
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001252 ass = codec->subsystem_id & 0xffff;
1253 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1254 goto do_sku;
1255
1256 /* invalid SSID, check the special NID pin defcfg instead */
1257 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001258 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001259 * 29~21 : reserve
1260 * 20 : PCBEEP input
1261 * 19~16 : Check sum (15:1)
1262 * 15~1 : Custom
1263 * 0 : override
1264 */
1265 nid = 0x1d;
1266 if (codec->vendor_id == 0x10ec0260)
1267 nid = 0x17;
1268 ass = snd_hda_codec_get_pincfg(codec, nid);
1269 snd_printd("realtek: No valid SSID, "
1270 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001271 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001272 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001273 return 0;
1274 if ((ass >> 30) != 1) /* no physical connection */
1275 return 0;
1276
1277 /* check sum */
1278 tmp = 0;
1279 for (i = 1; i < 16; i++) {
1280 if ((ass >> i) & 1)
1281 tmp++;
1282 }
1283 if (((ass >> 16) & 0xf) != tmp)
1284 return 0;
1285do_sku:
1286 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1287 ass & 0xffff, codec->vendor_id);
1288 /*
1289 * 0 : override
1290 * 1 : Swap Jack
1291 * 2 : 0 --> Desktop, 1 --> Laptop
1292 * 3~5 : External Amplifier control
1293 * 7~6 : Reserved
1294 */
1295 tmp = (ass & 0x38) >> 3; /* external Amp control */
1296 switch (tmp) {
1297 case 1:
1298 spec->init_amp = ALC_INIT_GPIO1;
1299 break;
1300 case 3:
1301 spec->init_amp = ALC_INIT_GPIO2;
1302 break;
1303 case 7:
1304 spec->init_amp = ALC_INIT_GPIO3;
1305 break;
1306 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001307 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001308 spec->init_amp = ALC_INIT_DEFAULT;
1309 break;
1310 }
1311
1312 /* is laptop or Desktop and enable the function "Mute internal speaker
1313 * when the external headphone out jack is plugged"
1314 */
1315 if (!(ass & 0x8000))
1316 return 1;
1317 /*
1318 * 10~8 : Jack location
1319 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1320 * 14~13: Resvered
1321 * 15 : 1 --> enable the function "Mute internal speaker
1322 * when the external headphone out jack is plugged"
1323 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001324 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001325 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001326 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1327 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001328 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001329 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001330 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001331 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001332 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001333 else if (tmp == 3)
1334 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001335 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001336 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001337 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1338 spec->autocfg.line_outs))
1339 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001340 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001341 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001342 return 1;
1343}
Kailang Yangea1fb292008-08-26 12:58:38 +02001344
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001345/* Check the validity of ALC subsystem-id
1346 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1347static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001348{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001349 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001350 struct alc_spec *spec = codec->spec;
1351 snd_printd("realtek: "
1352 "Enable default setup for auto mode as fallback\n");
1353 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001354 }
Takashi Iwai21268962011-07-07 15:01:13 +02001355}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001356
Takashi Iwai41e41f12005-06-08 14:48:49 +02001357/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001358 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001359 */
1360
1361struct alc_pincfg {
1362 hda_nid_t nid;
1363 u32 val;
1364};
1365
Todd Broche1eb5f12010-12-06 11:19:51 -08001366struct alc_model_fixup {
1367 const int id;
1368 const char *name;
1369};
1370
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001371struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001372 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001373 bool chained;
1374 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001375 union {
1376 unsigned int sku;
1377 const struct alc_pincfg *pins;
1378 const struct hda_verb *verbs;
1379 void (*func)(struct hda_codec *codec,
1380 const struct alc_fixup *fix,
1381 int action);
1382 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001383};
1384
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001385enum {
1386 ALC_FIXUP_INVALID,
1387 ALC_FIXUP_SKU,
1388 ALC_FIXUP_PINS,
1389 ALC_FIXUP_VERBS,
1390 ALC_FIXUP_FUNC,
1391};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001392
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001393enum {
1394 ALC_FIXUP_ACT_PRE_PROBE,
1395 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001396 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001397};
1398
1399static void alc_apply_fixup(struct hda_codec *codec, int action)
1400{
1401 struct alc_spec *spec = codec->spec;
1402 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001403#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001404 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001405#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001406 int depth = 0;
1407
1408 if (!spec->fixup_list)
1409 return;
1410
1411 while (id >= 0) {
1412 const struct alc_fixup *fix = spec->fixup_list + id;
1413 const struct alc_pincfg *cfg;
1414
1415 switch (fix->type) {
1416 case ALC_FIXUP_SKU:
1417 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1418 break;;
1419 snd_printdd(KERN_INFO "hda_codec: %s: "
1420 "Apply sku override for %s\n",
1421 codec->chip_name, modelname);
1422 spec->cdefine.sku_cfg = fix->v.sku;
1423 spec->cdefine.fixup = 1;
1424 break;
1425 case ALC_FIXUP_PINS:
1426 cfg = fix->v.pins;
1427 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1428 break;
1429 snd_printdd(KERN_INFO "hda_codec: %s: "
1430 "Apply pincfg for %s\n",
1431 codec->chip_name, modelname);
1432 for (; cfg->nid; cfg++)
1433 snd_hda_codec_set_pincfg(codec, cfg->nid,
1434 cfg->val);
1435 break;
1436 case ALC_FIXUP_VERBS:
1437 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1438 break;
1439 snd_printdd(KERN_INFO "hda_codec: %s: "
1440 "Apply fix-verbs for %s\n",
1441 codec->chip_name, modelname);
1442 add_verb(codec->spec, fix->v.verbs);
1443 break;
1444 case ALC_FIXUP_FUNC:
1445 if (!fix->v.func)
1446 break;
1447 snd_printdd(KERN_INFO "hda_codec: %s: "
1448 "Apply fix-func for %s\n",
1449 codec->chip_name, modelname);
1450 fix->v.func(codec, fix, action);
1451 break;
1452 default:
1453 snd_printk(KERN_ERR "hda_codec: %s: "
1454 "Invalid fixup type %d\n",
1455 codec->chip_name, fix->type);
1456 break;
1457 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001458 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001459 break;
1460 if (++depth > 10)
1461 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001462 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001463 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001464}
1465
Todd Broche1eb5f12010-12-06 11:19:51 -08001466static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001467 const struct alc_model_fixup *models,
1468 const struct snd_pci_quirk *quirk,
1469 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001470{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001471 struct alc_spec *spec = codec->spec;
1472 int id = -1;
1473 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001474
Todd Broche1eb5f12010-12-06 11:19:51 -08001475 if (codec->modelname && models) {
1476 while (models->name) {
1477 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001478 id = models->id;
1479 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001480 break;
1481 }
1482 models++;
1483 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001484 }
1485 if (id < 0) {
1486 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1487 if (quirk) {
1488 id = quirk->value;
1489#ifdef CONFIG_SND_DEBUG_VERBOSE
1490 name = quirk->name;
1491#endif
1492 }
1493 }
1494
1495 spec->fixup_id = id;
1496 if (id >= 0) {
1497 spec->fixup_list = fixlist;
1498 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001499 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001500}
1501
Takashi Iwai1d045db2011-07-07 18:23:21 +02001502/*
1503 * COEF access helper functions
1504 */
Kailang Yang274693f2009-12-03 10:07:50 +01001505static int alc_read_coef_idx(struct hda_codec *codec,
1506 unsigned int coef_idx)
1507{
1508 unsigned int val;
1509 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1510 coef_idx);
1511 val = snd_hda_codec_read(codec, 0x20, 0,
1512 AC_VERB_GET_PROC_COEF, 0);
1513 return val;
1514}
1515
Kailang Yang977ddd62010-09-15 10:02:29 +02001516static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1517 unsigned int coef_val)
1518{
1519 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1520 coef_idx);
1521 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1522 coef_val);
1523}
1524
Takashi Iwai1d045db2011-07-07 18:23:21 +02001525/*
1526 * Digital I/O handling
1527 */
1528
Takashi Iwai757899a2010-07-30 10:48:14 +02001529/* set right pin controls for digital I/O */
1530static void alc_auto_init_digital(struct hda_codec *codec)
1531{
1532 struct alc_spec *spec = codec->spec;
1533 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001534 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001535
1536 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1537 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001538 if (!pin)
1539 continue;
1540 snd_hda_codec_write(codec, pin, 0,
1541 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1542 if (!i)
1543 dac = spec->multiout.dig_out_nid;
1544 else
1545 dac = spec->slave_dig_outs[i - 1];
1546 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1547 continue;
1548 snd_hda_codec_write(codec, dac, 0,
1549 AC_VERB_SET_AMP_GAIN_MUTE,
1550 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001551 }
1552 pin = spec->autocfg.dig_in_pin;
1553 if (pin)
1554 snd_hda_codec_write(codec, pin, 0,
1555 AC_VERB_SET_PIN_WIDGET_CONTROL,
1556 PIN_IN);
1557}
1558
1559/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1560static void alc_auto_parse_digital(struct hda_codec *codec)
1561{
1562 struct alc_spec *spec = codec->spec;
1563 int i, err;
1564 hda_nid_t dig_nid;
1565
1566 /* support multiple SPDIFs; the secondary is set up as a slave */
1567 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001568 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001569 err = snd_hda_get_connections(codec,
1570 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001571 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001572 if (err < 0)
1573 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001574 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001575 if (!i) {
1576 spec->multiout.dig_out_nid = dig_nid;
1577 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1578 } else {
1579 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1580 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1581 break;
1582 spec->slave_dig_outs[i - 1] = dig_nid;
1583 }
1584 }
1585
1586 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001587 dig_nid = codec->start_nid;
1588 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1589 unsigned int wcaps = get_wcaps(codec, dig_nid);
1590 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1591 continue;
1592 if (!(wcaps & AC_WCAP_DIGITAL))
1593 continue;
1594 if (!(wcaps & AC_WCAP_CONN_LIST))
1595 continue;
1596 err = get_connection_index(codec, dig_nid,
1597 spec->autocfg.dig_in_pin);
1598 if (err >= 0) {
1599 spec->dig_in_nid = dig_nid;
1600 break;
1601 }
1602 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001603 }
1604}
1605
Takashi Iwaif95474e2007-07-10 00:47:43 +02001606/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001607 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001608 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001609static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1610 struct snd_ctl_elem_info *uinfo)
1611{
1612 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1613 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001614 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001615 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001616
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001617 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001618 if (spec->vol_in_capsrc)
1619 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1620 else
1621 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1622 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001623 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001624 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001625 return err;
1626}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001628static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1629 unsigned int size, unsigned int __user *tlv)
1630{
1631 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1632 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001633 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001634 int err;
1635
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001636 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001637 if (spec->vol_in_capsrc)
1638 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1639 else
1640 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1641 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001642 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001643 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001644 return err;
1645}
1646
1647typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1648 struct snd_ctl_elem_value *ucontrol);
1649
1650static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1651 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001652 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001653{
1654 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1655 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001656 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001657
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001658 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001659 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001660 for (i = 0; i < spec->num_adc_nids; i++) {
1661 kcontrol->private_value =
1662 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1663 3, 0, HDA_INPUT);
1664 err = func(kcontrol, ucontrol);
1665 if (err < 0)
1666 goto error;
1667 }
1668 } else {
1669 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001670 if (spec->vol_in_capsrc)
1671 kcontrol->private_value =
1672 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1673 3, 0, HDA_OUTPUT);
1674 else
1675 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001676 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1677 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001678 err = func(kcontrol, ucontrol);
1679 }
1680 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001681 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001682 return err;
1683}
1684
1685static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1686 struct snd_ctl_elem_value *ucontrol)
1687{
1688 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001689 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001690}
1691
1692static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1693 struct snd_ctl_elem_value *ucontrol)
1694{
1695 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001696 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001697}
1698
1699/* capture mixer elements */
1700#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1701
1702static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1703 struct snd_ctl_elem_value *ucontrol)
1704{
1705 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001706 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001707}
1708
1709static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1710 struct snd_ctl_elem_value *ucontrol)
1711{
1712 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001713 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001714}
1715
Takashi Iwaia23b6882009-03-23 15:21:36 +01001716#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001717 { \
1718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1719 .name = "Capture Switch", \
1720 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1721 .count = num, \
1722 .info = alc_cap_sw_info, \
1723 .get = alc_cap_sw_get, \
1724 .put = alc_cap_sw_put, \
1725 }, \
1726 { \
1727 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1728 .name = "Capture Volume", \
1729 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1730 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1731 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1732 .count = num, \
1733 .info = alc_cap_vol_info, \
1734 .get = alc_cap_vol_get, \
1735 .put = alc_cap_vol_put, \
1736 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001737 }
1738
1739#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001740 { \
1741 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1742 /* .name = "Capture Source", */ \
1743 .name = "Input Source", \
1744 .count = num, \
1745 .info = alc_mux_enum_info, \
1746 .get = alc_mux_enum_get, \
1747 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001748 }
1749
1750#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001751static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001752 _DEFINE_CAPMIX(num), \
1753 _DEFINE_CAPSRC(num), \
1754 { } /* end */ \
1755}
1756
1757#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001758static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001759 _DEFINE_CAPMIX(num), \
1760 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001761}
1762
1763/* up to three ADCs */
1764DEFINE_CAPMIX(1);
1765DEFINE_CAPMIX(2);
1766DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001767DEFINE_CAPMIX_NOSRC(1);
1768DEFINE_CAPMIX_NOSRC(2);
1769DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001770
1771/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001772 * virtual master controls
1773 */
1774
1775/*
1776 * slave controls for virtual master
1777 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001778static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001779 "Front Playback Volume",
1780 "Surround Playback Volume",
1781 "Center Playback Volume",
1782 "LFE Playback Volume",
1783 "Side Playback Volume",
1784 "Headphone Playback Volume",
1785 "Speaker Playback Volume",
1786 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001787 "Line-Out Playback Volume",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001788 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001789 NULL,
1790};
1791
Takashi Iwaiea734962011-01-17 11:29:34 +01001792static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001793 "Front Playback Switch",
1794 "Surround Playback Switch",
1795 "Center Playback Switch",
1796 "LFE Playback Switch",
1797 "Side Playback Switch",
1798 "Headphone Playback Switch",
1799 "Speaker Playback Switch",
1800 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001801 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001802 "Line-Out Playback Switch",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001803 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001804 NULL,
1805};
1806
1807/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001808 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001810
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001811#define NID_MAPPING (-1)
1812
1813#define SUBDEV_SPEAKER_ (0 << 6)
1814#define SUBDEV_HP_ (1 << 6)
1815#define SUBDEV_LINE_ (2 << 6)
1816#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1817#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1818#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1819
Takashi Iwai603c4012008-07-30 15:01:44 +02001820static void alc_free_kctls(struct hda_codec *codec);
1821
Takashi Iwai67d634c2009-11-16 15:35:59 +01001822#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001823/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001824static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001825 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001826 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001827 { } /* end */
1828};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001829#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001830
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831static int alc_build_controls(struct hda_codec *codec)
1832{
1833 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001834 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001835 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001836 int i, j, err;
1837 unsigned int u;
1838 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
1840 for (i = 0; i < spec->num_mixers; i++) {
1841 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1842 if (err < 0)
1843 return err;
1844 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001845 if (spec->cap_mixer) {
1846 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1847 if (err < 0)
1848 return err;
1849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001851 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001852 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001853 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 if (err < 0)
1855 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001856 if (!spec->no_analog) {
1857 err = snd_hda_create_spdif_share_sw(codec,
1858 &spec->multiout);
1859 if (err < 0)
1860 return err;
1861 spec->multiout.share_spdif = 1;
1862 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 }
1864 if (spec->dig_in_nid) {
1865 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1866 if (err < 0)
1867 return err;
1868 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001869
Takashi Iwai67d634c2009-11-16 15:35:59 +01001870#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001871 /* create beep controls if needed */
1872 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001873 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001874 for (knew = alc_beep_mixer; knew->name; knew++) {
1875 struct snd_kcontrol *kctl;
1876 kctl = snd_ctl_new1(knew, codec);
1877 if (!kctl)
1878 return -ENOMEM;
1879 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001880 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001881 if (err < 0)
1882 return err;
1883 }
1884 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001885#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001886
Takashi Iwai2134ea42008-01-10 16:53:55 +01001887 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001888 if (!spec->no_analog &&
1889 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001890 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001891 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001892 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001893 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001894 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001895 if (err < 0)
1896 return err;
1897 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001898 if (!spec->no_analog &&
1899 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001900 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1901 NULL, alc_slave_sws);
1902 if (err < 0)
1903 return err;
1904 }
1905
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001906 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001907 if (spec->capsrc_nids || spec->adc_nids) {
1908 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1909 if (!kctl)
1910 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1911 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001912 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001913 if (!nids)
1914 nids = spec->adc_nids;
1915 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1916 if (err < 0)
1917 return err;
1918 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001919 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001920 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001921 const char *kname = kctl ? kctl->id.name : NULL;
1922 for (knew = spec->cap_mixer; knew->name; knew++) {
1923 if (kname && strcmp(knew->name, kname) == 0)
1924 continue;
1925 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1926 for (i = 0; kctl && i < kctl->count; i++) {
1927 err = snd_hda_add_nid(codec, kctl, i,
1928 spec->adc_nids[i]);
1929 if (err < 0)
1930 return err;
1931 }
1932 }
1933 }
1934
1935 /* other nid->control mapping */
1936 for (i = 0; i < spec->num_mixers; i++) {
1937 for (knew = spec->mixers[i]; knew->name; knew++) {
1938 if (knew->iface != NID_MAPPING)
1939 continue;
1940 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1941 if (kctl == NULL)
1942 continue;
1943 u = knew->subdevice;
1944 for (j = 0; j < 4; j++, u >>= 8) {
1945 nid = u & 0x3f;
1946 if (nid == 0)
1947 continue;
1948 switch (u & 0xc0) {
1949 case SUBDEV_SPEAKER_:
1950 nid = spec->autocfg.speaker_pins[nid];
1951 break;
1952 case SUBDEV_LINE_:
1953 nid = spec->autocfg.line_out_pins[nid];
1954 break;
1955 case SUBDEV_HP_:
1956 nid = spec->autocfg.hp_pins[nid];
1957 break;
1958 default:
1959 continue;
1960 }
1961 err = snd_hda_add_nid(codec, kctl, 0, nid);
1962 if (err < 0)
1963 return err;
1964 }
1965 u = knew->private_value;
1966 for (j = 0; j < 4; j++, u >>= 8) {
1967 nid = u & 0xff;
1968 if (nid == 0)
1969 continue;
1970 err = snd_hda_add_nid(codec, kctl, 0, nid);
1971 if (err < 0)
1972 return err;
1973 }
1974 }
1975 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001976
1977 alc_free_kctls(codec); /* no longer needed */
1978
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 return 0;
1980}
1981
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001984 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001985 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001986
Takashi Iwai584c0c42011-03-10 12:51:11 +01001987static void alc_init_special_input_src(struct hda_codec *codec);
1988
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989static int alc_init(struct hda_codec *codec)
1990{
1991 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001992 unsigned int i;
1993
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001994 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001995 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001996
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001997 for (i = 0; i < spec->num_init_verbs; i++)
1998 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01001999 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002000
2001 if (spec->init_hook)
2002 spec->init_hook(codec);
2003
Takashi Iwai58701122011-01-13 15:41:45 +01002004 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2005
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002006 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 return 0;
2008}
2009
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002010static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2011{
2012 struct alc_spec *spec = codec->spec;
2013
2014 if (spec->unsol_event)
2015 spec->unsol_event(codec, res);
2016}
2017
Takashi Iwaicb53c622007-08-10 17:21:45 +02002018#ifdef CONFIG_SND_HDA_POWER_SAVE
2019static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2020{
2021 struct alc_spec *spec = codec->spec;
2022 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2023}
2024#endif
2025
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026/*
2027 * Analog playback callbacks
2028 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002029static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002031 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032{
2033 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002034 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2035 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036}
2037
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002038static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 struct hda_codec *codec,
2040 unsigned int stream_tag,
2041 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002042 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043{
2044 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002045 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2046 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047}
2048
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002049static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002051 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052{
2053 struct alc_spec *spec = codec->spec;
2054 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2055}
2056
2057/*
2058 * Digital out
2059 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002060static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002062 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063{
2064 struct alc_spec *spec = codec->spec;
2065 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2066}
2067
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002068static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002069 struct hda_codec *codec,
2070 unsigned int stream_tag,
2071 unsigned int format,
2072 struct snd_pcm_substream *substream)
2073{
2074 struct alc_spec *spec = codec->spec;
2075 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2076 stream_tag, format, substream);
2077}
2078
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002079static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002080 struct hda_codec *codec,
2081 struct snd_pcm_substream *substream)
2082{
2083 struct alc_spec *spec = codec->spec;
2084 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2085}
2086
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002087static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002089 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090{
2091 struct alc_spec *spec = codec->spec;
2092 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2093}
2094
2095/*
2096 * Analog capture
2097 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002098static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 struct hda_codec *codec,
2100 unsigned int stream_tag,
2101 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002102 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103{
2104 struct alc_spec *spec = codec->spec;
2105
Takashi Iwai63300792008-01-24 15:31:36 +01002106 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 stream_tag, 0, format);
2108 return 0;
2109}
2110
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002111static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002113 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114{
2115 struct alc_spec *spec = codec->spec;
2116
Takashi Iwai888afa12008-03-18 09:57:50 +01002117 snd_hda_codec_cleanup_stream(codec,
2118 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 return 0;
2120}
2121
Takashi Iwai840b64c2010-07-13 22:49:01 +02002122/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002123static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002124 struct hda_codec *codec,
2125 unsigned int stream_tag,
2126 unsigned int format,
2127 struct snd_pcm_substream *substream)
2128{
2129 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002130 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002131 spec->cur_adc_stream_tag = stream_tag;
2132 spec->cur_adc_format = format;
2133 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2134 return 0;
2135}
2136
Takashi Iwai21268962011-07-07 15:01:13 +02002137static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002138 struct hda_codec *codec,
2139 struct snd_pcm_substream *substream)
2140{
2141 struct alc_spec *spec = codec->spec;
2142 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2143 spec->cur_adc = 0;
2144 return 0;
2145}
2146
Takashi Iwai21268962011-07-07 15:01:13 +02002147static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002148 .substreams = 1,
2149 .channels_min = 2,
2150 .channels_max = 2,
2151 .nid = 0, /* fill later */
2152 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002153 .prepare = dyn_adc_capture_pcm_prepare,
2154 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002155 },
2156};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157
2158/*
2159 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002160static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 .substreams = 1,
2162 .channels_min = 2,
2163 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002164 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002166 .open = alc_playback_pcm_open,
2167 .prepare = alc_playback_pcm_prepare,
2168 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 },
2170};
2171
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002172static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002173 .substreams = 1,
2174 .channels_min = 2,
2175 .channels_max = 2,
2176 /* NID is set in alc_build_pcms */
2177};
2178
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002179static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002180 .substreams = 1,
2181 .channels_min = 2,
2182 .channels_max = 2,
2183 /* NID is set in alc_build_pcms */
2184};
2185
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002186static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002187 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 .channels_min = 2,
2189 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002190 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002192 .prepare = alc_alt_capture_pcm_prepare,
2193 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 },
2195};
2196
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002197static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 .substreams = 1,
2199 .channels_min = 2,
2200 .channels_max = 2,
2201 /* NID is set in alc_build_pcms */
2202 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002203 .open = alc_dig_playback_pcm_open,
2204 .close = alc_dig_playback_pcm_close,
2205 .prepare = alc_dig_playback_pcm_prepare,
2206 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 },
2208};
2209
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002210static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 .substreams = 1,
2212 .channels_min = 2,
2213 .channels_max = 2,
2214 /* NID is set in alc_build_pcms */
2215};
2216
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002217/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002218static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002219 .substreams = 0,
2220 .channels_min = 0,
2221 .channels_max = 0,
2222};
2223
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224static int alc_build_pcms(struct hda_codec *codec)
2225{
2226 struct alc_spec *spec = codec->spec;
2227 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002228 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 int i;
2230
2231 codec->num_pcms = 1;
2232 codec->pcm_info = info;
2233
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002234 if (spec->no_analog)
2235 goto skip_analog;
2236
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002237 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2238 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002240
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002241 if (spec->multiout.dac_nids > 0) {
2242 p = spec->stream_analog_playback;
2243 if (!p)
2244 p = &alc_pcm_analog_playback;
2245 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002246 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2247 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002248 if (spec->adc_nids) {
2249 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002250 if (!p) {
2251 if (spec->dyn_adc_switch)
2252 p = &dyn_adc_pcm_analog_capture;
2253 else
2254 p = &alc_pcm_analog_capture;
2255 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002256 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002257 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
Takashi Iwai4a471b72005-12-07 13:56:29 +01002260 if (spec->channel_mode) {
2261 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2262 for (i = 0; i < spec->num_channel_mode; i++) {
2263 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2264 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 }
2267 }
2268
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002269 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002270 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002272 snprintf(spec->stream_name_digital,
2273 sizeof(spec->stream_name_digital),
2274 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002275 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002276 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002277 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002279 if (spec->dig_out_type)
2280 info->pcm_type = spec->dig_out_type;
2281 else
2282 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002283 if (spec->multiout.dig_out_nid) {
2284 p = spec->stream_digital_playback;
2285 if (!p)
2286 p = &alc_pcm_digital_playback;
2287 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2289 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002290 if (spec->dig_in_nid) {
2291 p = spec->stream_digital_capture;
2292 if (!p)
2293 p = &alc_pcm_digital_capture;
2294 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2296 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002297 /* FIXME: do we need this for all Realtek codec models? */
2298 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 }
2300
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002301 if (spec->no_analog)
2302 return 0;
2303
Takashi Iwaie08a0072006-09-07 17:52:14 +02002304 /* If the use of more than one ADC is requested for the current
2305 * model, configure a second analog capture-only PCM.
2306 */
2307 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002308 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002309 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002310 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002311 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002312 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002313 p = spec->stream_analog_alt_playback;
2314 if (!p)
2315 p = &alc_pcm_analog_alt_playback;
2316 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002317 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2318 spec->alt_dac_nid;
2319 } else {
2320 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2321 alc_pcm_null_stream;
2322 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2323 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002324 if (spec->num_adc_nids > 1) {
2325 p = spec->stream_analog_alt_capture;
2326 if (!p)
2327 p = &alc_pcm_analog_alt_capture;
2328 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002329 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2330 spec->adc_nids[1];
2331 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2332 spec->num_adc_nids - 1;
2333 } else {
2334 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2335 alc_pcm_null_stream;
2336 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002337 }
2338 }
2339
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 return 0;
2341}
2342
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002343static inline void alc_shutup(struct hda_codec *codec)
2344{
Takashi Iwai1c716152011-04-07 10:37:16 +02002345 struct alc_spec *spec = codec->spec;
2346
2347 if (spec && spec->shutup)
2348 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002349 snd_hda_shutup_pins(codec);
2350}
2351
Takashi Iwai603c4012008-07-30 15:01:44 +02002352static void alc_free_kctls(struct hda_codec *codec)
2353{
2354 struct alc_spec *spec = codec->spec;
2355
2356 if (spec->kctls.list) {
2357 struct snd_kcontrol_new *kctl = spec->kctls.list;
2358 int i;
2359 for (i = 0; i < spec->kctls.used; i++)
2360 kfree(kctl[i].name);
2361 }
2362 snd_array_free(&spec->kctls);
2363}
2364
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365static void alc_free(struct hda_codec *codec)
2366{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002367 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002368
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002369 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002370 return;
2371
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002372 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002373 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002374 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002375 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002376 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377}
2378
Hector Martinf5de24b2009-12-20 22:51:31 +01002379#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002380static void alc_power_eapd(struct hda_codec *codec)
2381{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002382 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002383}
2384
Hector Martinf5de24b2009-12-20 22:51:31 +01002385static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2386{
2387 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002388 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002389 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002390 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002391 return 0;
2392}
2393#endif
2394
Takashi Iwai2a439522011-07-26 09:52:50 +02002395#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002396static int alc_resume(struct hda_codec *codec)
2397{
Takashi Iwai1c716152011-04-07 10:37:16 +02002398 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002399 codec->patch_ops.init(codec);
2400 snd_hda_codec_resume_amp(codec);
2401 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002402 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002403 return 0;
2404}
Takashi Iwaie044c392008-10-27 16:56:24 +01002405#endif
2406
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407/*
2408 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002409static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 .build_controls = alc_build_controls,
2411 .build_pcms = alc_build_pcms,
2412 .init = alc_init,
2413 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002414 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002415#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002416 .resume = alc_resume,
2417#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002418#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002419 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002420 .check_power_status = alc_check_power_status,
2421#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002422 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423};
2424
Kailang Yangc027ddc2010-03-19 11:33:06 +01002425/* replace the codec chip_name with the given string */
2426static int alc_codec_rename(struct hda_codec *codec, const char *name)
2427{
2428 kfree(codec->chip_name);
2429 codec->chip_name = kstrdup(name, GFP_KERNEL);
2430 if (!codec->chip_name) {
2431 alc_free(codec);
2432 return -ENOMEM;
2433 }
2434 return 0;
2435}
2436
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002437/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002438 * Automatic parse of I/O pins from the BIOS configuration
2439 */
2440
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002441enum {
2442 ALC_CTL_WIDGET_VOL,
2443 ALC_CTL_WIDGET_MUTE,
2444 ALC_CTL_BIND_MUTE,
2445};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002446static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002447 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2448 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002449 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002450};
2451
2452/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002453static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002454 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002455{
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002456 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002457
Takashi Iwaice764ab2011-04-27 16:35:23 +02002458 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002459 if (!knew)
2460 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002461 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002462 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002463 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002464 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002465 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002466 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002467 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002468 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002469 return 0;
2470}
2471
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002472static int add_control_with_pfx(struct alc_spec *spec, int type,
2473 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002474 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002475{
2476 char name[32];
2477 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002478 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002479}
2480
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002481#define add_pb_vol_ctrl(spec, type, pfx, val) \
2482 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2483#define add_pb_sw_ctrl(spec, type, pfx, val) \
2484 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2485#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2486 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2487#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2488 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002489
Takashi Iwai6843ca12011-06-24 11:03:58 +02002490static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2491 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002492{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002493 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002494 static const char * const chname[4] = {
2495 "Front", "Surround", NULL /*CLFE*/, "Side"
2496 };
Takashi Iwaice764ab2011-04-27 16:35:23 +02002497
Takashi Iwai6843ca12011-06-24 11:03:58 +02002498 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002499 if (cfg->line_outs == 1 && !spec->multi_ios &&
2500 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002501 return "Master";
2502
2503 switch (cfg->line_out_type) {
2504 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002505 if (cfg->line_outs == 1)
2506 return "Speaker";
2507 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002508 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002509 /* for multi-io case, only the primary out */
2510 if (ch && spec->multi_ios)
2511 break;
2512 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002513 return "Headphone";
2514 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002515 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002516 return "PCM";
2517 break;
2518 }
Takashi Iwai6843ca12011-06-24 11:03:58 +02002519 return chname[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002520}
2521
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002522/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002523static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002524 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002525 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002526{
Kailang Yangdf694da2005-12-05 19:42:22 +01002527 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002528
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002529 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002530 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2531 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002532 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002533 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002534 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2535 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002536 return err;
2537 return 0;
2538}
2539
Takashi Iwai05f5f472009-08-25 13:10:18 +02002540static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002541{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002542 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2543 return (pincap & AC_PINCAP_IN) != 0;
2544}
2545
Takashi Iwai1d045db2011-07-07 18:23:21 +02002546/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002547static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002548{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002549 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002550 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002551 hda_nid_t *adc_nids = spec->private_adc_nids;
2552 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2553 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2554 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002555 int i, nums = 0;
2556
2557 nid = codec->start_nid;
2558 for (i = 0; i < codec->num_nodes; i++, nid++) {
2559 hda_nid_t src;
2560 const hda_nid_t *list;
2561 unsigned int caps = get_wcaps(codec, nid);
2562 int type = get_wcaps_type(caps);
2563
2564 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2565 continue;
2566 adc_nids[nums] = nid;
2567 cap_nids[nums] = nid;
2568 src = nid;
2569 for (;;) {
2570 int n;
2571 type = get_wcaps_type(get_wcaps(codec, src));
2572 if (type == AC_WID_PIN)
2573 break;
2574 if (type == AC_WID_AUD_SEL) {
2575 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002576 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002577 break;
2578 }
2579 n = snd_hda_get_conn_list(codec, src, &list);
2580 if (n > 1) {
2581 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002582 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002583 break;
2584 } else if (n != 1)
2585 break;
2586 src = *list;
2587 }
2588 if (++nums >= max_nums)
2589 break;
2590 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002591 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002592 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002593 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002594 return nums;
2595}
2596
Takashi Iwai05f5f472009-08-25 13:10:18 +02002597/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002598static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002599{
2600 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002601 const struct auto_pin_cfg *cfg = &spec->autocfg;
2602 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002603 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002604 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002605 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002606 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002607
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002608 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002609 if (num_adcs < 0)
2610 return 0;
2611
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002612 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002613 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002614 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002615
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002616 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002617 if (!alc_is_input_pin(codec, pin))
2618 continue;
2619
David Henningsson5322bf22011-01-05 11:03:56 +01002620 label = hda_get_autocfg_input_label(codec, cfg, i);
2621 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002622 type_idx++;
2623 else
2624 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002625 prev_label = label;
2626
Takashi Iwai05f5f472009-08-25 13:10:18 +02002627 if (mixer) {
2628 idx = get_connection_index(codec, mixer, pin);
2629 if (idx >= 0) {
2630 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002631 label, type_idx,
2632 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002633 if (err < 0)
2634 return err;
2635 }
2636 }
2637
Takashi Iwaib7821702011-07-06 15:12:46 +02002638 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002639 hda_nid_t cap = spec->capsrc_nids ?
2640 spec->capsrc_nids[c] : spec->adc_nids[c];
2641 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002642 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002643 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002644 snd_hda_add_imux_item(imux, label, idx, NULL);
2645 break;
2646 }
2647 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002648 }
Takashi Iwai21268962011-07-07 15:01:13 +02002649
2650 spec->num_mux_defs = 1;
2651 spec->input_mux = imux;
2652
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002653 return 0;
2654}
2655
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002656static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2657 unsigned int pin_type)
2658{
2659 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2660 pin_type);
2661 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002662 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2663 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002664 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002665}
2666
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002667static int get_pin_type(int line_out_type)
2668{
2669 if (line_out_type == AUTO_PIN_HP_OUT)
2670 return PIN_HP;
2671 else
2672 return PIN_OUT;
2673}
2674
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002675static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002676{
2677 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002678 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002679 int i;
2680
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002681 for (i = 0; i < cfg->num_inputs; i++) {
2682 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002683 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002684 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002685 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002686 snd_hda_codec_write(codec, nid, 0,
2687 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002688 AMP_OUT_MUTE);
2689 }
2690 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002691
2692 /* mute all loopback inputs */
2693 if (spec->mixer_nid) {
2694 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2695 for (i = 0; i < nums; i++)
2696 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2697 AC_VERB_SET_AMP_GAIN_MUTE,
2698 AMP_IN_MUTE(i));
2699 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002700}
2701
Takashi Iwai7085ec12009-10-02 09:03:58 +02002702/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002703static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002704{
Takashi Iwai604401a2011-04-27 15:14:23 +02002705 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002706 int i, num;
2707
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002708 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2709 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002710 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2711 for (i = 0; i < num; i++) {
2712 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2713 return list[i];
2714 }
2715 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002716}
2717
Takashi Iwai604401a2011-04-27 15:14:23 +02002718/* go down to the selector widget before the mixer */
2719static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2720{
2721 hda_nid_t srcs[5];
2722 int num = snd_hda_get_connections(codec, pin, srcs,
2723 ARRAY_SIZE(srcs));
2724 if (num != 1 ||
2725 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2726 return pin;
2727 return srcs[0];
2728}
2729
Takashi Iwai7085ec12009-10-02 09:03:58 +02002730/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002731static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002732 hda_nid_t dac)
2733{
David Henningssoncc1c4522010-11-24 14:17:47 +01002734 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002735 int i, num;
2736
Takashi Iwai604401a2011-04-27 15:14:23 +02002737 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002738 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2739 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002740 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002741 return mix[i];
2742 }
2743 return 0;
2744}
2745
Takashi Iwaice764ab2011-04-27 16:35:23 +02002746/* select the connection from pin to DAC if needed */
2747static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2748 hda_nid_t dac)
2749{
2750 hda_nid_t mix[5];
2751 int i, num;
2752
2753 pin = alc_go_down_to_selector(codec, pin);
2754 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2755 if (num < 2)
2756 return 0;
2757 for (i = 0; i < num; i++) {
2758 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2759 snd_hda_codec_update_cache(codec, pin, 0,
2760 AC_VERB_SET_CONNECT_SEL, i);
2761 return 0;
2762 }
2763 }
2764 return 0;
2765}
2766
Takashi Iwai7085ec12009-10-02 09:03:58 +02002767/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002768static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002769{
2770 struct alc_spec *spec = codec->spec;
2771 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002772 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002773
Takashi Iwai604401a2011-04-27 15:14:23 +02002774 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002775 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002776 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002777 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002778 if (!nid)
2779 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002780 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2781 spec->multiout.num_dacs))
2782 continue;
2783 if (spec->multiout.hp_nid == nid)
2784 continue;
2785 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2786 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2787 continue;
2788 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002789 }
2790 return 0;
2791}
2792
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002793static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2794{
2795 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2796 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2797 return alc_auto_look_for_dac(codec, pin);
2798 return 0;
2799}
2800
Takashi Iwai7085ec12009-10-02 09:03:58 +02002801/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002802static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002803{
2804 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002805 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002806 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002807 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002808
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002809 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002810 /* set num_dacs once to full for alc_auto_look_for_dac() */
2811 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002812 spec->multiout.hp_nid = 0;
2813 spec->multiout.extra_out_nid[0] = 0;
2814 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2815 spec->multiout.dac_nids = spec->private_dac_nids;
2816
2817 /* fill hard-wired DACs first */
2818 if (!redone) {
2819 for (i = 0; i < cfg->line_outs; i++)
2820 spec->private_dac_nids[i] =
2821 get_dac_if_single(codec, cfg->line_out_pins[i]);
2822 if (cfg->hp_outs)
2823 spec->multiout.hp_nid =
2824 get_dac_if_single(codec, cfg->hp_pins[0]);
2825 if (cfg->speaker_outs)
2826 spec->multiout.extra_out_nid[0] =
2827 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002828 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002829
2830 for (i = 0; i < cfg->line_outs; i++) {
2831 hda_nid_t pin = cfg->line_out_pins[i];
2832 if (spec->private_dac_nids[i])
2833 continue;
2834 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2835 if (!spec->private_dac_nids[i] && !redone) {
2836 /* if we can't find primary DACs, re-probe without
2837 * checking the hard-wired DACs
2838 */
2839 redone = true;
2840 goto again;
2841 }
2842 }
2843
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002844 /* re-count num_dacs and squash invalid entries */
2845 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002846 for (i = 0; i < cfg->line_outs; i++) {
2847 if (spec->private_dac_nids[i])
2848 spec->multiout.num_dacs++;
2849 else
2850 memmove(spec->private_dac_nids + i,
2851 spec->private_dac_nids + i + 1,
2852 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2853 }
2854
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002855 if (cfg->hp_outs && !spec->multiout.hp_nid)
2856 spec->multiout.hp_nid =
2857 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2858 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2859 spec->multiout.extra_out_nid[0] =
2860 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2861
Takashi Iwai7085ec12009-10-02 09:03:58 +02002862 return 0;
2863}
2864
Takashi Iwai343a04b2011-07-06 14:28:39 +02002865static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002866 const char *pfx, int cidx,
2867 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002868{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002869 if (!nid)
2870 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002871 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2872 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002873}
2874
Takashi Iwai343a04b2011-07-06 14:28:39 +02002875#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2876 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002877
2878/* create a mute-switch for the given mixer widget;
2879 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2880 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002881static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002882 const char *pfx, int cidx,
2883 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002884{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002885 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002886 int type;
2887 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002888 if (!nid)
2889 return 0;
2890 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2891 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2892 type = ALC_CTL_WIDGET_MUTE;
2893 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2894 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002895 type = ALC_CTL_WIDGET_MUTE;
2896 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2897 } else {
2898 type = ALC_CTL_BIND_MUTE;
2899 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2900 }
2901 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002902}
2903
Takashi Iwai343a04b2011-07-06 14:28:39 +02002904#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2905 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002906
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002907static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2908 hda_nid_t pin, hda_nid_t dac)
2909{
2910 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2911 if (nid_has_mute(codec, pin, HDA_OUTPUT))
2912 return pin;
2913 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
2914 return mix;
2915 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
2916 return dac;
2917 return 0;
2918}
2919
2920static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
2921 hda_nid_t pin, hda_nid_t dac)
2922{
2923 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2924 if (nid_has_volume(codec, dac, HDA_OUTPUT))
2925 return dac;
2926 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
2927 return mix;
2928 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
2929 return pin;
2930 return 0;
2931}
2932
Takashi Iwai7085ec12009-10-02 09:03:58 +02002933/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002934static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002935 const struct auto_pin_cfg *cfg)
2936{
2937 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002938 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002939
Takashi Iwaice764ab2011-04-27 16:35:23 +02002940 noutputs = cfg->line_outs;
2941 if (spec->multi_ios > 0)
2942 noutputs += spec->multi_ios;
2943
2944 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002945 const char *name;
2946 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002947 hda_nid_t dac, pin;
2948 hda_nid_t sw, vol;
2949
2950 dac = spec->multiout.dac_nids[i];
2951 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002952 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002953 if (i >= cfg->line_outs)
2954 pin = spec->multi_io[i - 1].pin;
2955 else
2956 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002957
2958 sw = alc_look_for_out_mute_nid(codec, pin, dac);
2959 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02002960 name = alc_get_line_out_pfx(spec, i, true, &index);
2961 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002962 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002963 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
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_vol_ctl(codec, "LFE", 0, vol, 2);
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, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002970 if (err < 0)
2971 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002972 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002973 if (err < 0)
2974 return err;
2975 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002976 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002977 if (err < 0)
2978 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002979 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002980 if (err < 0)
2981 return err;
2982 }
2983 }
2984 return 0;
2985}
2986
2987/* add playback controls for speaker and HP outputs */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002988static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002989 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002990{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002991 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002992 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002993 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002994
2995 if (!pin)
2996 return 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002997 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02002998 /* the corresponding DAC is already occupied */
2999 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
3000 return 0; /* no way */
3001 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02003002 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003003 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3004 }
3005
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003006 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3007 vol = alc_look_for_out_vol_nid(codec, pin, dac);
3008 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003009 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003010 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003011 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003012 if (err < 0)
3013 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003014 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003015}
3016
Takashi Iwai343a04b2011-07-06 14:28:39 +02003017static int alc_auto_create_hp_out(struct hda_codec *codec)
3018{
3019 struct alc_spec *spec = codec->spec;
3020 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3021 spec->multiout.hp_nid,
3022 "Headphone");
3023}
3024
3025static int alc_auto_create_speaker_out(struct hda_codec *codec)
3026{
3027 struct alc_spec *spec = codec->spec;
3028 return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
3029 spec->multiout.extra_out_nid[0],
3030 "Speaker");
3031}
3032
Takashi Iwai343a04b2011-07-06 14:28:39 +02003033static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003034 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003035 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003036{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003037 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003038 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003039 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003040
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003041 alc_set_pin_output(codec, pin, pin_type);
3042 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003043 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003044 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003045 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003046 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003047 mix = srcs[i];
3048 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003049 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003050 if (!mix)
3051 return;
3052
3053 /* need the manual connection? */
3054 if (num > 1)
3055 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3056 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003057 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3058 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003059 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003060 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003061 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003062 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003063 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003064 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3065 if (nid)
3066 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3067 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003068}
3069
Takashi Iwai343a04b2011-07-06 14:28:39 +02003070static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003071{
3072 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003073 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003074 int i;
3075
3076 for (i = 0; i <= HDA_SIDE; i++) {
3077 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3078 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003079 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003080 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003081 }
3082}
3083
Takashi Iwai343a04b2011-07-06 14:28:39 +02003084static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003085{
3086 struct alc_spec *spec = codec->spec;
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003087 hda_nid_t pin, dac;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003088
3089 pin = spec->autocfg.hp_pins[0];
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003090 if (pin) {
3091 dac = spec->multiout.hp_nid;
3092 if (!dac)
3093 dac = spec->multiout.dac_nids[0];
3094 alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
3095 }
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003096 pin = spec->autocfg.speaker_pins[0];
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003097 if (pin) {
3098 dac = spec->multiout.extra_out_nid[0];
3099 if (!dac)
3100 dac = spec->multiout.dac_nids[0];
3101 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
3102 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003103}
3104
Takashi Iwaice764ab2011-04-27 16:35:23 +02003105/*
3106 * multi-io helper
3107 */
3108static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3109 unsigned int location)
3110{
3111 struct alc_spec *spec = codec->spec;
3112 struct auto_pin_cfg *cfg = &spec->autocfg;
3113 int type, i, num_pins = 0;
3114
3115 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3116 for (i = 0; i < cfg->num_inputs; i++) {
3117 hda_nid_t nid = cfg->inputs[i].pin;
3118 hda_nid_t dac;
3119 unsigned int defcfg, caps;
3120 if (cfg->inputs[i].type != type)
3121 continue;
3122 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3123 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3124 continue;
3125 if (location && get_defcfg_location(defcfg) != location)
3126 continue;
3127 caps = snd_hda_query_pin_caps(codec, nid);
3128 if (!(caps & AC_PINCAP_OUT))
3129 continue;
3130 dac = alc_auto_look_for_dac(codec, nid);
3131 if (!dac)
3132 continue;
3133 spec->multi_io[num_pins].pin = nid;
3134 spec->multi_io[num_pins].dac = dac;
3135 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003136 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003137 }
3138 }
3139 spec->multiout.num_dacs = 1;
3140 if (num_pins < 2)
3141 return 0;
3142 return num_pins;
3143}
3144
3145static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3146 struct snd_ctl_elem_info *uinfo)
3147{
3148 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3149 struct alc_spec *spec = codec->spec;
3150
3151 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3152 uinfo->count = 1;
3153 uinfo->value.enumerated.items = spec->multi_ios + 1;
3154 if (uinfo->value.enumerated.item > spec->multi_ios)
3155 uinfo->value.enumerated.item = spec->multi_ios;
3156 sprintf(uinfo->value.enumerated.name, "%dch",
3157 (uinfo->value.enumerated.item + 1) * 2);
3158 return 0;
3159}
3160
3161static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3162 struct snd_ctl_elem_value *ucontrol)
3163{
3164 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3165 struct alc_spec *spec = codec->spec;
3166 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3167 return 0;
3168}
3169
3170static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3171{
3172 struct alc_spec *spec = codec->spec;
3173 hda_nid_t nid = spec->multi_io[idx].pin;
3174
3175 if (!spec->multi_io[idx].ctl_in)
3176 spec->multi_io[idx].ctl_in =
3177 snd_hda_codec_read(codec, nid, 0,
3178 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3179 if (output) {
3180 snd_hda_codec_update_cache(codec, nid, 0,
3181 AC_VERB_SET_PIN_WIDGET_CONTROL,
3182 PIN_OUT);
3183 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3184 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3185 HDA_AMP_MUTE, 0);
3186 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3187 } else {
3188 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3189 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3190 HDA_AMP_MUTE, HDA_AMP_MUTE);
3191 snd_hda_codec_update_cache(codec, nid, 0,
3192 AC_VERB_SET_PIN_WIDGET_CONTROL,
3193 spec->multi_io[idx].ctl_in);
3194 }
3195 return 0;
3196}
3197
3198static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3199 struct snd_ctl_elem_value *ucontrol)
3200{
3201 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3202 struct alc_spec *spec = codec->spec;
3203 int i, ch;
3204
3205 ch = ucontrol->value.enumerated.item[0];
3206 if (ch < 0 || ch > spec->multi_ios)
3207 return -EINVAL;
3208 if (ch == (spec->ext_channel_count - 1) / 2)
3209 return 0;
3210 spec->ext_channel_count = (ch + 1) * 2;
3211 for (i = 0; i < spec->multi_ios; i++)
3212 alc_set_multi_io(codec, i, i < ch);
3213 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003214 if (spec->need_dac_fix && !spec->const_channel_count)
3215 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003216 return 1;
3217}
3218
Takashi Iwaia9111322011-05-02 11:30:18 +02003219static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003220 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3221 .name = "Channel Mode",
3222 .info = alc_auto_ch_mode_info,
3223 .get = alc_auto_ch_mode_get,
3224 .put = alc_auto_ch_mode_put,
3225};
3226
Takashi Iwaicb053a82011-06-27 11:32:07 +02003227static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
3228 int (*fill_dac)(struct hda_codec *))
Takashi Iwaice764ab2011-04-27 16:35:23 +02003229{
3230 struct alc_spec *spec = codec->spec;
3231 struct auto_pin_cfg *cfg = &spec->autocfg;
3232 unsigned int location, defcfg;
3233 int num_pins;
3234
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003235 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3236 /* use HP as primary out */
3237 cfg->speaker_outs = cfg->line_outs;
3238 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3239 sizeof(cfg->speaker_pins));
3240 cfg->line_outs = cfg->hp_outs;
3241 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3242 cfg->hp_outs = 0;
3243 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3244 cfg->line_out_type = AUTO_PIN_HP_OUT;
Takashi Iwaicb053a82011-06-27 11:32:07 +02003245 if (fill_dac)
3246 fill_dac(codec);
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003247 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003248 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003249 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003250 return 0;
3251
3252 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3253 location = get_defcfg_location(defcfg);
3254
3255 num_pins = alc_auto_fill_multi_ios(codec, location);
3256 if (num_pins > 0) {
3257 struct snd_kcontrol_new *knew;
3258
3259 knew = alc_kcontrol_new(spec);
3260 if (!knew)
3261 return -ENOMEM;
3262 *knew = alc_auto_channel_mode_enum;
3263 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3264 if (!knew->name)
3265 return -ENOMEM;
3266
3267 spec->multi_ios = num_pins;
3268 spec->ext_channel_count = 2;
3269 spec->multiout.num_dacs = num_pins + 1;
3270 }
3271 return 0;
3272}
3273
Takashi Iwai1d045db2011-07-07 18:23:21 +02003274/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3275 * active input pins
3276 */
3277static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3278{
3279 struct alc_spec *spec = codec->spec;
3280 const struct hda_input_mux *imux;
3281 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3282 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3283 int i, n, nums;
3284
3285 imux = spec->input_mux;
3286 if (!imux)
3287 return;
3288 if (spec->dyn_adc_switch)
3289 return;
3290
3291 nums = 0;
3292 for (n = 0; n < spec->num_adc_nids; n++) {
3293 hda_nid_t cap = spec->private_capsrc_nids[n];
3294 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3295 for (i = 0; i < imux->num_items; i++) {
3296 hda_nid_t pin = spec->imux_pins[i];
3297 if (pin) {
3298 if (get_connection_index(codec, cap, pin) < 0)
3299 break;
3300 } else if (num_conns <= imux->items[i].index)
3301 break;
3302 }
3303 if (i >= imux->num_items) {
3304 adc_nids[nums] = spec->private_adc_nids[n];
3305 capsrc_nids[nums++] = cap;
3306 }
3307 }
3308 if (!nums) {
3309 /* check whether ADC-switch is possible */
3310 if (!alc_check_dyn_adc_switch(codec)) {
3311 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3312 " using fallback 0x%x\n",
3313 codec->chip_name, spec->private_adc_nids[0]);
3314 spec->num_adc_nids = 1;
3315 spec->auto_mic = 0;
3316 return;
3317 }
3318 } else if (nums != spec->num_adc_nids) {
3319 memcpy(spec->private_adc_nids, adc_nids,
3320 nums * sizeof(hda_nid_t));
3321 memcpy(spec->private_capsrc_nids, capsrc_nids,
3322 nums * sizeof(hda_nid_t));
3323 spec->num_adc_nids = nums;
3324 }
3325
3326 if (spec->auto_mic)
3327 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3328 else if (spec->input_mux->num_items == 1)
3329 spec->num_adc_nids = 1; /* reduce to a single ADC */
3330}
3331
3332/*
3333 * initialize ADC paths
3334 */
3335static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3336{
3337 struct alc_spec *spec = codec->spec;
3338 hda_nid_t nid;
3339
3340 nid = spec->adc_nids[adc_idx];
3341 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003342 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003343 snd_hda_codec_write(codec, nid, 0,
3344 AC_VERB_SET_AMP_GAIN_MUTE,
3345 AMP_IN_MUTE(0));
3346 return;
3347 }
3348 if (!spec->capsrc_nids)
3349 return;
3350 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003351 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003352 snd_hda_codec_write(codec, nid, 0,
3353 AC_VERB_SET_AMP_GAIN_MUTE,
3354 AMP_OUT_MUTE);
3355}
3356
3357static void alc_auto_init_input_src(struct hda_codec *codec)
3358{
3359 struct alc_spec *spec = codec->spec;
3360 int c, nums;
3361
3362 for (c = 0; c < spec->num_adc_nids; c++)
3363 alc_auto_init_adc(codec, c);
3364 if (spec->dyn_adc_switch)
3365 nums = 1;
3366 else
3367 nums = spec->num_adc_nids;
3368 for (c = 0; c < nums; c++)
3369 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3370}
3371
3372/* add mic boosts if needed */
3373static int alc_auto_add_mic_boost(struct hda_codec *codec)
3374{
3375 struct alc_spec *spec = codec->spec;
3376 struct auto_pin_cfg *cfg = &spec->autocfg;
3377 int i, err;
3378 int type_idx = 0;
3379 hda_nid_t nid;
3380 const char *prev_label = NULL;
3381
3382 for (i = 0; i < cfg->num_inputs; i++) {
3383 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3384 break;
3385 nid = cfg->inputs[i].pin;
3386 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3387 const char *label;
3388 char boost_label[32];
3389
3390 label = hda_get_autocfg_input_label(codec, cfg, i);
3391 if (prev_label && !strcmp(label, prev_label))
3392 type_idx++;
3393 else
3394 type_idx = 0;
3395 prev_label = label;
3396
3397 snprintf(boost_label, sizeof(boost_label),
3398 "%s Boost Volume", label);
3399 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3400 boost_label, type_idx,
3401 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3402 if (err < 0)
3403 return err;
3404 }
3405 }
3406 return 0;
3407}
3408
3409/* select or unmute the given capsrc route */
3410static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3411 int idx)
3412{
3413 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3414 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3415 HDA_AMP_MUTE, 0);
3416 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3417 snd_hda_codec_write_cache(codec, cap, 0,
3418 AC_VERB_SET_CONNECT_SEL, idx);
3419 }
3420}
3421
3422/* set the default connection to that pin */
3423static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3424{
3425 struct alc_spec *spec = codec->spec;
3426 int i;
3427
3428 if (!pin)
3429 return 0;
3430 for (i = 0; i < spec->num_adc_nids; i++) {
3431 hda_nid_t cap = spec->capsrc_nids ?
3432 spec->capsrc_nids[i] : spec->adc_nids[i];
3433 int idx;
3434
3435 idx = get_connection_index(codec, cap, pin);
3436 if (idx < 0)
3437 continue;
3438 select_or_unmute_capsrc(codec, cap, idx);
3439 return i; /* return the found index */
3440 }
3441 return -1; /* not found */
3442}
3443
3444/* initialize some special cases for input sources */
3445static void alc_init_special_input_src(struct hda_codec *codec)
3446{
3447 struct alc_spec *spec = codec->spec;
3448 int i;
3449
3450 for (i = 0; i < spec->autocfg.num_inputs; i++)
3451 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3452}
3453
3454/* assign appropriate capture mixers */
3455static void set_capture_mixer(struct hda_codec *codec)
3456{
3457 struct alc_spec *spec = codec->spec;
3458 static const struct snd_kcontrol_new *caps[2][3] = {
3459 { alc_capture_mixer_nosrc1,
3460 alc_capture_mixer_nosrc2,
3461 alc_capture_mixer_nosrc3 },
3462 { alc_capture_mixer1,
3463 alc_capture_mixer2,
3464 alc_capture_mixer3 },
3465 };
3466
3467 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003468 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003469 if (!spec->capsrc_nids)
3470 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003471 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003472 return; /* no volume in capsrc, too */
3473 spec->vol_in_capsrc = 1;
3474 }
3475
3476 if (spec->num_adc_nids > 0) {
3477 int mux = 0;
3478 int num_adcs = 0;
3479
3480 if (spec->input_mux && spec->input_mux->num_items > 1)
3481 mux = 1;
3482 if (spec->auto_mic) {
3483 num_adcs = 1;
3484 mux = 0;
3485 } else if (spec->dyn_adc_switch)
3486 num_adcs = 1;
3487 if (!num_adcs) {
3488 if (spec->num_adc_nids > 3)
3489 spec->num_adc_nids = 3;
3490 else if (!spec->num_adc_nids)
3491 return;
3492 num_adcs = spec->num_adc_nids;
3493 }
3494 spec->cap_mixer = caps[mux][num_adcs - 1];
3495 }
3496}
3497
3498/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003499 * standard auto-parser initializations
3500 */
3501static void alc_auto_init_std(struct hda_codec *codec)
3502{
3503 struct alc_spec *spec = codec->spec;
3504 alc_auto_init_multi_out(codec);
3505 alc_auto_init_extra_out(codec);
3506 alc_auto_init_analog_input(codec);
3507 alc_auto_init_input_src(codec);
3508 alc_auto_init_digital(codec);
3509 if (spec->unsol_event)
3510 alc_inithook(codec);
3511}
3512
3513/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003514 * Digital-beep handlers
3515 */
3516#ifdef CONFIG_SND_HDA_INPUT_BEEP
3517#define set_beep_amp(spec, nid, idx, dir) \
3518 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3519
3520static const struct snd_pci_quirk beep_white_list[] = {
3521 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3522 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3523 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3524 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3525 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3526 {}
3527};
3528
3529static inline int has_cdefine_beep(struct hda_codec *codec)
3530{
3531 struct alc_spec *spec = codec->spec;
3532 const struct snd_pci_quirk *q;
3533 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3534 if (q)
3535 return q->value;
3536 return spec->cdefine.enable_pcbeep;
3537}
3538#else
3539#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3540#define has_cdefine_beep(codec) 0
3541#endif
3542
3543/* parse the BIOS configuration and set up the alc_spec */
3544/* return 1 if successful, 0 if the proper config is not found,
3545 * or a negative error code
3546 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003547static int alc_parse_auto_config(struct hda_codec *codec,
3548 const hda_nid_t *ignore_nids,
3549 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003550{
3551 struct alc_spec *spec = codec->spec;
3552 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003553
3554 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003555 ignore_nids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003556 if (err < 0)
3557 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003558 if (!spec->autocfg.line_outs) {
3559 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
3560 spec->multiout.max_channels = 2;
3561 spec->no_analog = 1;
3562 goto dig_only;
3563 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003564 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003565 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003566 err = alc_auto_fill_dac_nids(codec);
3567 if (err < 0)
3568 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003569 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
3570 if (err < 0)
3571 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003572 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
3573 if (err < 0)
3574 return err;
3575 err = alc_auto_create_hp_out(codec);
3576 if (err < 0)
3577 return err;
3578 err = alc_auto_create_speaker_out(codec);
3579 if (err < 0)
3580 return err;
3581 err = alc_auto_create_input_ctls(codec);
3582 if (err < 0)
3583 return err;
3584
3585 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3586
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003587 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02003588 alc_auto_parse_digital(codec);
3589
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003590 if (!spec->no_analog)
3591 alc_remove_invalid_adc_nids(codec);
3592
3593 if (ssid_nids)
3594 alc_ssid_check(codec, ssid_nids);
3595
3596 if (!spec->no_analog) {
3597 alc_auto_check_switches(codec);
3598 err = alc_auto_add_mic_boost(codec);
3599 if (err < 0)
3600 return err;
3601 }
3602
Takashi Iwai1d045db2011-07-07 18:23:21 +02003603 if (spec->kctls.list)
3604 add_mixer(spec, spec->kctls.list);
3605
Takashi Iwai1d045db2011-07-07 18:23:21 +02003606 return 1;
3607}
3608
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003609static int alc880_parse_auto_config(struct hda_codec *codec)
3610{
3611 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3612 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3613 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
3614}
3615
Takashi Iwai1d045db2011-07-07 18:23:21 +02003616#ifdef CONFIG_SND_HDA_POWER_SAVE
3617static const struct hda_amp_list alc880_loopbacks[] = {
3618 { 0x0b, HDA_INPUT, 0 },
3619 { 0x0b, HDA_INPUT, 1 },
3620 { 0x0b, HDA_INPUT, 2 },
3621 { 0x0b, HDA_INPUT, 3 },
3622 { 0x0b, HDA_INPUT, 4 },
3623 { } /* end */
3624};
3625#endif
3626
3627/*
3628 * board setups
3629 */
3630#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3631#define alc_board_config \
3632 snd_hda_check_board_config
3633#define alc_board_codec_sid_config \
3634 snd_hda_check_board_codec_sid_config
3635#include "alc_quirks.c"
3636#else
3637#define alc_board_config(codec, nums, models, tbl) -1
3638#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3639#define setup_preset(codec, x) /* NOP */
3640#endif
3641
3642/*
3643 * OK, here we have finally the patch for ALC880
3644 */
3645#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3646#include "alc880_quirks.c"
3647#endif
3648
3649static int patch_alc880(struct hda_codec *codec)
3650{
3651 struct alc_spec *spec;
3652 int board_config;
3653 int err;
3654
3655 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3656 if (spec == NULL)
3657 return -ENOMEM;
3658
3659 codec->spec = spec;
3660
3661 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003662 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003663
3664 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3665 alc880_models, alc880_cfg_tbl);
3666 if (board_config < 0) {
3667 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3668 codec->chip_name);
3669 board_config = ALC_MODEL_AUTO;
3670 }
3671
3672 if (board_config == ALC_MODEL_AUTO) {
3673 /* automatic parse from the BIOS config */
3674 err = alc880_parse_auto_config(codec);
3675 if (err < 0) {
3676 alc_free(codec);
3677 return err;
3678 }
3679#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3680 else if (!err) {
3681 printk(KERN_INFO
3682 "hda_codec: Cannot set up configuration "
3683 "from BIOS. Using 3-stack mode...\n");
3684 board_config = ALC880_3ST;
3685 }
3686#endif
3687 }
3688
Takashi Iwai1d045db2011-07-07 18:23:21 +02003689 if (board_config != ALC_MODEL_AUTO)
3690 setup_preset(codec, &alc880_presets[board_config]);
3691
Takashi Iwai60a6a842011-07-27 14:01:24 +02003692 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003693 alc_auto_fill_adc_caps(codec);
3694 alc_rebuild_imux_for_auto_mic(codec);
3695 alc_remove_invalid_adc_nids(codec);
3696 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003697
3698 if (!spec->no_analog && !spec->cap_mixer)
3699 set_capture_mixer(codec);
3700
3701 if (!spec->no_analog) {
3702 err = snd_hda_attach_beep_device(codec, 0x1);
3703 if (err < 0) {
3704 alc_free(codec);
3705 return err;
3706 }
3707 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3708 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003709
3710 spec->vmaster_nid = 0x0c;
3711
3712 codec->patch_ops = alc_patch_ops;
3713 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003714 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003715#ifdef CONFIG_SND_HDA_POWER_SAVE
3716 if (!spec->loopback.amplist)
3717 spec->loopback.amplist = alc880_loopbacks;
3718#endif
3719
3720 return 0;
3721}
3722
3723
3724/*
3725 * ALC260 support
3726 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003727static int alc260_parse_auto_config(struct hda_codec *codec)
3728{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003729 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003730 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
3731 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003732}
3733
Takashi Iwai1d045db2011-07-07 18:23:21 +02003734#ifdef CONFIG_SND_HDA_POWER_SAVE
3735static const struct hda_amp_list alc260_loopbacks[] = {
3736 { 0x07, HDA_INPUT, 0 },
3737 { 0x07, HDA_INPUT, 1 },
3738 { 0x07, HDA_INPUT, 2 },
3739 { 0x07, HDA_INPUT, 3 },
3740 { 0x07, HDA_INPUT, 4 },
3741 { } /* end */
3742};
3743#endif
3744
3745/*
3746 * Pin config fixes
3747 */
3748enum {
3749 PINFIX_HP_DC5750,
3750};
3751
3752static const struct alc_fixup alc260_fixups[] = {
3753 [PINFIX_HP_DC5750] = {
3754 .type = ALC_FIXUP_PINS,
3755 .v.pins = (const struct alc_pincfg[]) {
3756 { 0x11, 0x90130110 }, /* speaker */
3757 { }
3758 }
3759 },
3760};
3761
3762static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3763 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3764 {}
3765};
3766
3767/*
3768 */
3769#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3770#include "alc260_quirks.c"
3771#endif
3772
3773static int patch_alc260(struct hda_codec *codec)
3774{
3775 struct alc_spec *spec;
3776 int err, board_config;
3777
3778 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3779 if (spec == NULL)
3780 return -ENOMEM;
3781
3782 codec->spec = spec;
3783
3784 spec->mixer_nid = 0x07;
3785
3786 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3787 alc260_models, alc260_cfg_tbl);
3788 if (board_config < 0) {
3789 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3790 codec->chip_name);
3791 board_config = ALC_MODEL_AUTO;
3792 }
3793
3794 if (board_config == ALC_MODEL_AUTO) {
3795 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3796 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3797 }
3798
3799 if (board_config == ALC_MODEL_AUTO) {
3800 /* automatic parse from the BIOS config */
3801 err = alc260_parse_auto_config(codec);
3802 if (err < 0) {
3803 alc_free(codec);
3804 return err;
3805 }
3806#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3807 else if (!err) {
3808 printk(KERN_INFO
3809 "hda_codec: Cannot set up configuration "
3810 "from BIOS. Using base mode...\n");
3811 board_config = ALC260_BASIC;
3812 }
3813#endif
3814 }
3815
Takashi Iwai1d045db2011-07-07 18:23:21 +02003816 if (board_config != ALC_MODEL_AUTO)
3817 setup_preset(codec, &alc260_presets[board_config]);
3818
Takashi Iwai60a6a842011-07-27 14:01:24 +02003819 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003820 alc_auto_fill_adc_caps(codec);
3821 alc_rebuild_imux_for_auto_mic(codec);
3822 alc_remove_invalid_adc_nids(codec);
3823 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003824
3825 if (!spec->no_analog && !spec->cap_mixer)
3826 set_capture_mixer(codec);
3827
3828 if (!spec->no_analog) {
3829 err = snd_hda_attach_beep_device(codec, 0x1);
3830 if (err < 0) {
3831 alc_free(codec);
3832 return err;
3833 }
3834 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3835 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003836
3837 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3838
3839 spec->vmaster_nid = 0x08;
3840
3841 codec->patch_ops = alc_patch_ops;
3842 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02003843 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003844 spec->shutup = alc_eapd_shutup;
3845#ifdef CONFIG_SND_HDA_POWER_SAVE
3846 if (!spec->loopback.amplist)
3847 spec->loopback.amplist = alc260_loopbacks;
3848#endif
3849
3850 return 0;
3851}
3852
3853
3854/*
3855 * ALC882/883/885/888/889 support
3856 *
3857 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3858 * configuration. Each pin widget can choose any input DACs and a mixer.
3859 * Each ADC is connected from a mixer of all inputs. This makes possible
3860 * 6-channel independent captures.
3861 *
3862 * In addition, an independent DAC for the multi-playback (not used in this
3863 * driver yet).
3864 */
3865#ifdef CONFIG_SND_HDA_POWER_SAVE
3866#define alc882_loopbacks alc880_loopbacks
3867#endif
3868
3869/*
3870 * Pin config fixes
3871 */
3872enum {
3873 PINFIX_ABIT_AW9D_MAX,
3874 PINFIX_LENOVO_Y530,
3875 PINFIX_PB_M5210,
3876 PINFIX_ACER_ASPIRE_7736,
3877};
3878
3879static const struct alc_fixup alc882_fixups[] = {
3880 [PINFIX_ABIT_AW9D_MAX] = {
3881 .type = ALC_FIXUP_PINS,
3882 .v.pins = (const struct alc_pincfg[]) {
3883 { 0x15, 0x01080104 }, /* side */
3884 { 0x16, 0x01011012 }, /* rear */
3885 { 0x17, 0x01016011 }, /* clfe */
3886 { }
3887 }
3888 },
3889 [PINFIX_LENOVO_Y530] = {
3890 .type = ALC_FIXUP_PINS,
3891 .v.pins = (const struct alc_pincfg[]) {
3892 { 0x15, 0x99130112 }, /* rear int speakers */
3893 { 0x16, 0x99130111 }, /* subwoofer */
3894 { }
3895 }
3896 },
3897 [PINFIX_PB_M5210] = {
3898 .type = ALC_FIXUP_VERBS,
3899 .v.verbs = (const struct hda_verb[]) {
3900 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
3901 {}
3902 }
3903 },
3904 [PINFIX_ACER_ASPIRE_7736] = {
3905 .type = ALC_FIXUP_SKU,
3906 .v.sku = ALC_FIXUP_SKU_IGNORE,
3907 },
3908};
3909
3910static const struct snd_pci_quirk alc882_fixup_tbl[] = {
3911 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
3912 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
3913 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
3914 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
3915 {}
3916};
3917
3918/*
3919 * BIOS auto configuration
3920 */
3921/* almost identical with ALC880 parser... */
3922static int alc882_parse_auto_config(struct hda_codec *codec)
3923{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003924 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003925 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3926 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003927}
3928
Takashi Iwai1d045db2011-07-07 18:23:21 +02003929/*
3930 */
3931#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3932#include "alc882_quirks.c"
3933#endif
3934
3935static int patch_alc882(struct hda_codec *codec)
3936{
3937 struct alc_spec *spec;
3938 int err, board_config;
3939
3940 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3941 if (spec == NULL)
3942 return -ENOMEM;
3943
3944 codec->spec = spec;
3945
3946 spec->mixer_nid = 0x0b;
3947
3948 switch (codec->vendor_id) {
3949 case 0x10ec0882:
3950 case 0x10ec0885:
3951 break;
3952 default:
3953 /* ALC883 and variants */
3954 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
3955 break;
3956 }
3957
3958 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
3959 alc882_models, alc882_cfg_tbl);
3960
3961 if (board_config < 0)
3962 board_config = alc_board_codec_sid_config(codec,
3963 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
3964
3965 if (board_config < 0) {
3966 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3967 codec->chip_name);
3968 board_config = ALC_MODEL_AUTO;
3969 }
3970
3971 if (board_config == ALC_MODEL_AUTO) {
3972 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
3973 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3974 }
3975
3976 alc_auto_parse_customize_define(codec);
3977
3978 if (board_config == ALC_MODEL_AUTO) {
3979 /* automatic parse from the BIOS config */
3980 err = alc882_parse_auto_config(codec);
3981 if (err < 0) {
3982 alc_free(codec);
3983 return err;
3984 }
3985#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3986 else if (!err) {
3987 printk(KERN_INFO
3988 "hda_codec: Cannot set up configuration "
3989 "from BIOS. Using base mode...\n");
3990 board_config = ALC882_3ST_DIG;
3991 }
3992#endif
3993 }
3994
Takashi Iwai1d045db2011-07-07 18:23:21 +02003995 if (board_config != ALC_MODEL_AUTO)
3996 setup_preset(codec, &alc882_presets[board_config]);
3997
Takashi Iwai60a6a842011-07-27 14:01:24 +02003998 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003999 alc_auto_fill_adc_caps(codec);
4000 alc_rebuild_imux_for_auto_mic(codec);
4001 alc_remove_invalid_adc_nids(codec);
4002 }
4003
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004004 if (!spec->no_analog && !spec->cap_mixer)
4005 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004006
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004007 if (!spec->no_analog && has_cdefine_beep(codec)) {
4008 err = snd_hda_attach_beep_device(codec, 0x1);
4009 if (err < 0) {
4010 alc_free(codec);
4011 return err;
4012 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004013 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004014 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004015
4016 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4017
4018 spec->vmaster_nid = 0x0c;
4019
4020 codec->patch_ops = alc_patch_ops;
4021 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004022 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004023
4024 alc_init_jacks(codec);
4025#ifdef CONFIG_SND_HDA_POWER_SAVE
4026 if (!spec->loopback.amplist)
4027 spec->loopback.amplist = alc882_loopbacks;
4028#endif
4029
4030 return 0;
4031}
4032
4033
4034/*
4035 * ALC262 support
4036 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004037static int alc262_parse_auto_config(struct hda_codec *codec)
4038{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004039 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004040 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4041 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004042}
4043
4044/*
4045 * Pin config fixes
4046 */
4047enum {
4048 PINFIX_FSC_H270,
4049 PINFIX_HP_Z200,
4050};
4051
4052static const struct alc_fixup alc262_fixups[] = {
4053 [PINFIX_FSC_H270] = {
4054 .type = ALC_FIXUP_PINS,
4055 .v.pins = (const struct alc_pincfg[]) {
4056 { 0x14, 0x99130110 }, /* speaker */
4057 { 0x15, 0x0221142f }, /* front HP */
4058 { 0x1b, 0x0121141f }, /* rear HP */
4059 { }
4060 }
4061 },
4062 [PINFIX_HP_Z200] = {
4063 .type = ALC_FIXUP_PINS,
4064 .v.pins = (const struct alc_pincfg[]) {
4065 { 0x16, 0x99130120 }, /* internal speaker */
4066 { }
4067 }
4068 },
4069};
4070
4071static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4072 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4073 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4074 {}
4075};
4076
4077
4078#ifdef CONFIG_SND_HDA_POWER_SAVE
4079#define alc262_loopbacks alc880_loopbacks
4080#endif
4081
Takashi Iwai1d045db2011-07-07 18:23:21 +02004082/*
4083 */
4084#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4085#include "alc262_quirks.c"
4086#endif
4087
4088static int patch_alc262(struct hda_codec *codec)
4089{
4090 struct alc_spec *spec;
4091 int board_config;
4092 int err;
4093
4094 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4095 if (spec == NULL)
4096 return -ENOMEM;
4097
4098 codec->spec = spec;
4099
4100 spec->mixer_nid = 0x0b;
4101
4102#if 0
4103 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4104 * under-run
4105 */
4106 {
4107 int tmp;
4108 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4109 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4110 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4111 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4112 }
4113#endif
4114 alc_auto_parse_customize_define(codec);
4115
4116 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4117
4118 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4119 alc262_models, alc262_cfg_tbl);
4120
4121 if (board_config < 0) {
4122 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4123 codec->chip_name);
4124 board_config = ALC_MODEL_AUTO;
4125 }
4126
4127 if (board_config == ALC_MODEL_AUTO) {
4128 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4129 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4130 }
4131
4132 if (board_config == ALC_MODEL_AUTO) {
4133 /* automatic parse from the BIOS config */
4134 err = alc262_parse_auto_config(codec);
4135 if (err < 0) {
4136 alc_free(codec);
4137 return err;
4138 }
4139#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4140 else if (!err) {
4141 printk(KERN_INFO
4142 "hda_codec: Cannot set up configuration "
4143 "from BIOS. Using base mode...\n");
4144 board_config = ALC262_BASIC;
4145 }
4146#endif
4147 }
4148
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004149 if (board_config != ALC_MODEL_AUTO)
4150 setup_preset(codec, &alc262_presets[board_config]);
4151
Takashi Iwai60a6a842011-07-27 14:01:24 +02004152 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004153 alc_auto_fill_adc_caps(codec);
4154 alc_rebuild_imux_for_auto_mic(codec);
4155 alc_remove_invalid_adc_nids(codec);
4156 }
4157
4158 if (!spec->no_analog && !spec->cap_mixer)
4159 set_capture_mixer(codec);
4160
Takashi Iwai1d045db2011-07-07 18:23:21 +02004161 if (!spec->no_analog && has_cdefine_beep(codec)) {
4162 err = snd_hda_attach_beep_device(codec, 0x1);
4163 if (err < 0) {
4164 alc_free(codec);
4165 return err;
4166 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004167 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004168 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004169
4170 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4171
4172 spec->vmaster_nid = 0x0c;
4173
4174 codec->patch_ops = alc_patch_ops;
4175 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004176 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004177 spec->shutup = alc_eapd_shutup;
4178
4179 alc_init_jacks(codec);
4180#ifdef CONFIG_SND_HDA_POWER_SAVE
4181 if (!spec->loopback.amplist)
4182 spec->loopback.amplist = alc262_loopbacks;
4183#endif
4184
4185 return 0;
4186}
4187
4188/*
4189 * ALC268
4190 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004191/* bind Beep switches of both NID 0x0f and 0x10 */
4192static const struct hda_bind_ctls alc268_bind_beep_sw = {
4193 .ops = &snd_hda_bind_sw,
4194 .values = {
4195 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4196 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4197 0
4198 },
4199};
4200
4201static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4202 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4203 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4204 { }
4205};
4206
4207/* set PCBEEP vol = 0, mute connections */
4208static const struct hda_verb alc268_beep_init_verbs[] = {
4209 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4210 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4211 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4212 { }
4213};
4214
4215/*
4216 * BIOS auto configuration
4217 */
4218static int alc268_parse_auto_config(struct hda_codec *codec)
4219{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004220 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004221 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004222 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4223 if (err > 0) {
4224 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4225 add_mixer(spec, alc268_beep_mixer);
4226 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004227 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004228 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004229 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004230}
4231
Takashi Iwai1d045db2011-07-07 18:23:21 +02004232/*
4233 */
4234#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4235#include "alc268_quirks.c"
4236#endif
4237
4238static int patch_alc268(struct hda_codec *codec)
4239{
4240 struct alc_spec *spec;
4241 int board_config;
4242 int i, has_beep, err;
4243
4244 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4245 if (spec == NULL)
4246 return -ENOMEM;
4247
4248 codec->spec = spec;
4249
4250 /* ALC268 has no aa-loopback mixer */
4251
4252 board_config = alc_board_config(codec, ALC268_MODEL_LAST,
4253 alc268_models, alc268_cfg_tbl);
4254
4255 if (board_config < 0)
4256 board_config = alc_board_codec_sid_config(codec,
4257 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
4258
4259 if (board_config < 0) {
4260 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4261 codec->chip_name);
4262 board_config = ALC_MODEL_AUTO;
4263 }
4264
4265 if (board_config == ALC_MODEL_AUTO) {
4266 /* automatic parse from the BIOS config */
4267 err = alc268_parse_auto_config(codec);
4268 if (err < 0) {
4269 alc_free(codec);
4270 return err;
4271 }
4272#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4273 else if (!err) {
4274 printk(KERN_INFO
4275 "hda_codec: Cannot set up configuration "
4276 "from BIOS. Using base mode...\n");
4277 board_config = ALC268_3ST;
4278 }
4279#endif
4280 }
4281
4282 if (board_config != ALC_MODEL_AUTO)
4283 setup_preset(codec, &alc268_presets[board_config]);
4284
4285 has_beep = 0;
4286 for (i = 0; i < spec->num_mixers; i++) {
4287 if (spec->mixers[i] == alc268_beep_mixer) {
4288 has_beep = 1;
4289 break;
4290 }
4291 }
4292
4293 if (has_beep) {
4294 err = snd_hda_attach_beep_device(codec, 0x1);
4295 if (err < 0) {
4296 alc_free(codec);
4297 return err;
4298 }
4299 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4300 /* override the amp caps for beep generator */
4301 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4302 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4303 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4304 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4305 (0 << AC_AMPCAP_MUTE_SHIFT));
4306 }
4307
Takashi Iwai60a6a842011-07-27 14:01:24 +02004308 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004309 alc_auto_fill_adc_caps(codec);
4310 alc_rebuild_imux_for_auto_mic(codec);
4311 alc_remove_invalid_adc_nids(codec);
4312 }
4313
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004314 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004315 set_capture_mixer(codec);
4316
4317 spec->vmaster_nid = 0x02;
4318
4319 codec->patch_ops = alc_patch_ops;
4320 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004321 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004322 spec->shutup = alc_eapd_shutup;
4323
4324 alc_init_jacks(codec);
4325
4326 return 0;
4327}
4328
4329/*
4330 * ALC269
4331 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004332#ifdef CONFIG_SND_HDA_POWER_SAVE
4333#define alc269_loopbacks alc880_loopbacks
4334#endif
4335
4336static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4337 .substreams = 1,
4338 .channels_min = 2,
4339 .channels_max = 8,
4340 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4341 /* NID is set in alc_build_pcms */
4342 .ops = {
4343 .open = alc_playback_pcm_open,
4344 .prepare = alc_playback_pcm_prepare,
4345 .cleanup = alc_playback_pcm_cleanup
4346 },
4347};
4348
4349static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4350 .substreams = 1,
4351 .channels_min = 2,
4352 .channels_max = 2,
4353 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4354 /* NID is set in alc_build_pcms */
4355};
4356
4357#ifdef CONFIG_SND_HDA_POWER_SAVE
4358static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4359{
4360 switch (codec->subsystem_id) {
4361 case 0x103c1586:
4362 return 1;
4363 }
4364 return 0;
4365}
4366
4367static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4368{
4369 /* update mute-LED according to the speaker mute state */
4370 if (nid == 0x01 || nid == 0x14) {
4371 int pinval;
4372 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4373 HDA_AMP_MUTE)
4374 pinval = 0x24;
4375 else
4376 pinval = 0x20;
4377 /* mic2 vref pin is used for mute LED control */
4378 snd_hda_codec_update_cache(codec, 0x19, 0,
4379 AC_VERB_SET_PIN_WIDGET_CONTROL,
4380 pinval);
4381 }
4382 return alc_check_power_status(codec, nid);
4383}
4384#endif /* CONFIG_SND_HDA_POWER_SAVE */
4385
4386/* different alc269-variants */
4387enum {
4388 ALC269_TYPE_ALC269VA,
4389 ALC269_TYPE_ALC269VB,
4390 ALC269_TYPE_ALC269VC,
4391};
4392
4393/*
4394 * BIOS auto configuration
4395 */
4396static int alc269_parse_auto_config(struct hda_codec *codec)
4397{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004398 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004399 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
4400 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4401 struct alc_spec *spec = codec->spec;
4402 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
4403 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004404
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004405 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004406}
4407
Takashi Iwai1d045db2011-07-07 18:23:21 +02004408static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4409{
4410 int val = alc_read_coef_idx(codec, 0x04);
4411 if (power_up)
4412 val |= 1 << 11;
4413 else
4414 val &= ~(1 << 11);
4415 alc_write_coef_idx(codec, 0x04, val);
4416}
4417
4418static void alc269_shutup(struct hda_codec *codec)
4419{
4420 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4421 alc269_toggle_power_output(codec, 0);
4422 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4423 alc269_toggle_power_output(codec, 0);
4424 msleep(150);
4425 }
4426}
4427
Takashi Iwai2a439522011-07-26 09:52:50 +02004428#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004429static int alc269_resume(struct hda_codec *codec)
4430{
4431 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4432 alc269_toggle_power_output(codec, 0);
4433 msleep(150);
4434 }
4435
4436 codec->patch_ops.init(codec);
4437
4438 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4439 alc269_toggle_power_output(codec, 1);
4440 msleep(200);
4441 }
4442
4443 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4444 alc269_toggle_power_output(codec, 1);
4445
4446 snd_hda_codec_resume_amp(codec);
4447 snd_hda_codec_resume_cache(codec);
4448 hda_call_check_power_status(codec, 0x01);
4449 return 0;
4450}
Takashi Iwai2a439522011-07-26 09:52:50 +02004451#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004452
4453static void alc269_fixup_hweq(struct hda_codec *codec,
4454 const struct alc_fixup *fix, int action)
4455{
4456 int coef;
4457
4458 if (action != ALC_FIXUP_ACT_INIT)
4459 return;
4460 coef = alc_read_coef_idx(codec, 0x1e);
4461 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4462}
4463
4464static void alc271_fixup_dmic(struct hda_codec *codec,
4465 const struct alc_fixup *fix, int action)
4466{
4467 static const struct hda_verb verbs[] = {
4468 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4469 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4470 {}
4471 };
4472 unsigned int cfg;
4473
4474 if (strcmp(codec->chip_name, "ALC271X"))
4475 return;
4476 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4477 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4478 snd_hda_sequence_write(codec, verbs);
4479}
4480
Takashi Iwai017f2a12011-07-09 14:42:25 +02004481static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4482 const struct alc_fixup *fix, int action)
4483{
4484 struct alc_spec *spec = codec->spec;
4485
4486 if (action != ALC_FIXUP_ACT_PROBE)
4487 return;
4488
4489 /* Due to a hardware problem on Lenovo Ideadpad, we need to
4490 * fix the sample rate of analog I/O to 44.1kHz
4491 */
4492 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
4493 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4494}
4495
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004496static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4497 const struct alc_fixup *fix, int action)
4498{
4499 int coef;
4500
4501 if (action != ALC_FIXUP_ACT_INIT)
4502 return;
4503 /* The digital-mic unit sends PDM (differential signal) instead of
4504 * the standard PCM, thus you can't record a valid mono stream as is.
4505 * Below is a workaround specific to ALC269 to control the dmic
4506 * signal source as mono.
4507 */
4508 coef = alc_read_coef_idx(codec, 0x07);
4509 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4510}
4511
Takashi Iwai1d045db2011-07-07 18:23:21 +02004512enum {
4513 ALC269_FIXUP_SONY_VAIO,
4514 ALC275_FIXUP_SONY_VAIO_GPIO2,
4515 ALC269_FIXUP_DELL_M101Z,
4516 ALC269_FIXUP_SKU_IGNORE,
4517 ALC269_FIXUP_ASUS_G73JW,
4518 ALC269_FIXUP_LENOVO_EAPD,
4519 ALC275_FIXUP_SONY_HWEQ,
4520 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004521 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004522 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004523};
4524
4525static const struct alc_fixup alc269_fixups[] = {
4526 [ALC269_FIXUP_SONY_VAIO] = {
4527 .type = ALC_FIXUP_VERBS,
4528 .v.verbs = (const struct hda_verb[]) {
4529 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4530 {}
4531 }
4532 },
4533 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4534 .type = ALC_FIXUP_VERBS,
4535 .v.verbs = (const struct hda_verb[]) {
4536 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4537 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4538 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4539 { }
4540 },
4541 .chained = true,
4542 .chain_id = ALC269_FIXUP_SONY_VAIO
4543 },
4544 [ALC269_FIXUP_DELL_M101Z] = {
4545 .type = ALC_FIXUP_VERBS,
4546 .v.verbs = (const struct hda_verb[]) {
4547 /* Enables internal speaker */
4548 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4549 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4550 {}
4551 }
4552 },
4553 [ALC269_FIXUP_SKU_IGNORE] = {
4554 .type = ALC_FIXUP_SKU,
4555 .v.sku = ALC_FIXUP_SKU_IGNORE,
4556 },
4557 [ALC269_FIXUP_ASUS_G73JW] = {
4558 .type = ALC_FIXUP_PINS,
4559 .v.pins = (const struct alc_pincfg[]) {
4560 { 0x17, 0x99130111 }, /* subwoofer */
4561 { }
4562 }
4563 },
4564 [ALC269_FIXUP_LENOVO_EAPD] = {
4565 .type = ALC_FIXUP_VERBS,
4566 .v.verbs = (const struct hda_verb[]) {
4567 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4568 {}
4569 }
4570 },
4571 [ALC275_FIXUP_SONY_HWEQ] = {
4572 .type = ALC_FIXUP_FUNC,
4573 .v.func = alc269_fixup_hweq,
4574 .chained = true,
4575 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4576 },
4577 [ALC271_FIXUP_DMIC] = {
4578 .type = ALC_FIXUP_FUNC,
4579 .v.func = alc271_fixup_dmic,
4580 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004581 [ALC269_FIXUP_PCM_44K] = {
4582 .type = ALC_FIXUP_FUNC,
4583 .v.func = alc269_fixup_pcm_44k,
4584 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004585 [ALC269_FIXUP_STEREO_DMIC] = {
4586 .type = ALC_FIXUP_FUNC,
4587 .v.func = alc269_fixup_stereo_dmic,
4588 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004589};
4590
4591static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02004592 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004593 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4594 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4595 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4596 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4597 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004598 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4599 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4600 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4601 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4602 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4603 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
4604 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4605 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4606 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4607 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4608 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02004609 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004610 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
4611 {}
4612};
4613
4614
4615static int alc269_fill_coef(struct hda_codec *codec)
4616{
4617 int val;
4618
4619 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4620 alc_write_coef_idx(codec, 0xf, 0x960b);
4621 alc_write_coef_idx(codec, 0xe, 0x8817);
4622 }
4623
4624 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4625 alc_write_coef_idx(codec, 0xf, 0x960b);
4626 alc_write_coef_idx(codec, 0xe, 0x8814);
4627 }
4628
4629 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4630 val = alc_read_coef_idx(codec, 0x04);
4631 /* Power up output pin */
4632 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4633 }
4634
4635 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4636 val = alc_read_coef_idx(codec, 0xd);
4637 if ((val & 0x0c00) >> 10 != 0x1) {
4638 /* Capless ramp up clock control */
4639 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4640 }
4641 val = alc_read_coef_idx(codec, 0x17);
4642 if ((val & 0x01c0) >> 6 != 0x4) {
4643 /* Class D power on reset */
4644 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4645 }
4646 }
4647
4648 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4649 alc_write_coef_idx(codec, 0xd, val | (1<<14));
4650
4651 val = alc_read_coef_idx(codec, 0x4); /* HP */
4652 alc_write_coef_idx(codec, 0x4, val | (1<<11));
4653
4654 return 0;
4655}
4656
4657/*
4658 */
4659#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4660#include "alc269_quirks.c"
4661#endif
4662
4663static int patch_alc269(struct hda_codec *codec)
4664{
4665 struct alc_spec *spec;
4666 int board_config, coef;
4667 int err;
4668
4669 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4670 if (spec == NULL)
4671 return -ENOMEM;
4672
4673 codec->spec = spec;
4674
4675 spec->mixer_nid = 0x0b;
4676
4677 alc_auto_parse_customize_define(codec);
4678
4679 if (codec->vendor_id == 0x10ec0269) {
4680 spec->codec_variant = ALC269_TYPE_ALC269VA;
4681 coef = alc_read_coef_idx(codec, 0);
4682 if ((coef & 0x00f0) == 0x0010) {
4683 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
4684 spec->cdefine.platform_type == 1) {
4685 alc_codec_rename(codec, "ALC271X");
4686 } else if ((coef & 0xf000) == 0x2000) {
4687 alc_codec_rename(codec, "ALC259");
4688 } else if ((coef & 0xf000) == 0x3000) {
4689 alc_codec_rename(codec, "ALC258");
4690 } else if ((coef & 0xfff0) == 0x3010) {
4691 alc_codec_rename(codec, "ALC277");
4692 } else {
4693 alc_codec_rename(codec, "ALC269VB");
4694 }
4695 spec->codec_variant = ALC269_TYPE_ALC269VB;
4696 } else if ((coef & 0x00f0) == 0x0020) {
4697 if (coef == 0xa023)
4698 alc_codec_rename(codec, "ALC259");
4699 else if (coef == 0x6023)
4700 alc_codec_rename(codec, "ALC281X");
4701 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4702 codec->bus->pci->subsystem_device == 0x21f3)
4703 alc_codec_rename(codec, "ALC3202");
4704 else
4705 alc_codec_rename(codec, "ALC269VC");
4706 spec->codec_variant = ALC269_TYPE_ALC269VC;
4707 } else
4708 alc_fix_pll_init(codec, 0x20, 0x04, 15);
4709 alc269_fill_coef(codec);
4710 }
4711
4712 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
4713 alc269_models, alc269_cfg_tbl);
4714
4715 if (board_config < 0) {
4716 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4717 codec->chip_name);
4718 board_config = ALC_MODEL_AUTO;
4719 }
4720
4721 if (board_config == ALC_MODEL_AUTO) {
4722 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
4723 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4724 }
4725
4726 if (board_config == ALC_MODEL_AUTO) {
4727 /* automatic parse from the BIOS config */
4728 err = alc269_parse_auto_config(codec);
4729 if (err < 0) {
4730 alc_free(codec);
4731 return err;
4732 }
4733#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4734 else if (!err) {
4735 printk(KERN_INFO
4736 "hda_codec: Cannot set up configuration "
4737 "from BIOS. Using base mode...\n");
4738 board_config = ALC269_BASIC;
4739 }
4740#endif
4741 }
4742
Takashi Iwai1d045db2011-07-07 18:23:21 +02004743 if (board_config != ALC_MODEL_AUTO)
4744 setup_preset(codec, &alc269_presets[board_config]);
4745
Takashi Iwai60a6a842011-07-27 14:01:24 +02004746 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004747 alc_auto_fill_adc_caps(codec);
4748 alc_rebuild_imux_for_auto_mic(codec);
4749 alc_remove_invalid_adc_nids(codec);
4750 }
4751
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004752 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004753 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004754
4755 if (!spec->no_analog && has_cdefine_beep(codec)) {
4756 err = snd_hda_attach_beep_device(codec, 0x1);
4757 if (err < 0) {
4758 alc_free(codec);
4759 return err;
4760 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004761 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004762 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004763
4764 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4765
4766 spec->vmaster_nid = 0x02;
4767
4768 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02004769#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004770 codec->patch_ops.resume = alc269_resume;
4771#endif
4772 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004773 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004774 spec->shutup = alc269_shutup;
4775
4776 alc_init_jacks(codec);
4777#ifdef CONFIG_SND_HDA_POWER_SAVE
4778 if (!spec->loopback.amplist)
4779 spec->loopback.amplist = alc269_loopbacks;
4780 if (alc269_mic2_for_mute_led(codec))
4781 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
4782#endif
4783
4784 return 0;
4785}
4786
4787/*
4788 * ALC861
4789 */
4790
Takashi Iwai1d045db2011-07-07 18:23:21 +02004791static int alc861_parse_auto_config(struct hda_codec *codec)
4792{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004793 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004794 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4795 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004796}
4797
Takashi Iwai1d045db2011-07-07 18:23:21 +02004798#ifdef CONFIG_SND_HDA_POWER_SAVE
4799static const struct hda_amp_list alc861_loopbacks[] = {
4800 { 0x15, HDA_INPUT, 0 },
4801 { 0x15, HDA_INPUT, 1 },
4802 { 0x15, HDA_INPUT, 2 },
4803 { 0x15, HDA_INPUT, 3 },
4804 { } /* end */
4805};
4806#endif
4807
4808
4809/* Pin config fixes */
4810enum {
4811 PINFIX_FSC_AMILO_PI1505,
4812};
4813
4814static const struct alc_fixup alc861_fixups[] = {
4815 [PINFIX_FSC_AMILO_PI1505] = {
4816 .type = ALC_FIXUP_PINS,
4817 .v.pins = (const struct alc_pincfg[]) {
4818 { 0x0b, 0x0221101f }, /* HP */
4819 { 0x0f, 0x90170310 }, /* speaker */
4820 { }
4821 }
4822 },
4823};
4824
4825static const struct snd_pci_quirk alc861_fixup_tbl[] = {
4826 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
4827 {}
4828};
4829
4830/*
4831 */
4832#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4833#include "alc861_quirks.c"
4834#endif
4835
4836static int patch_alc861(struct hda_codec *codec)
4837{
4838 struct alc_spec *spec;
4839 int board_config;
4840 int err;
4841
4842 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4843 if (spec == NULL)
4844 return -ENOMEM;
4845
4846 codec->spec = spec;
4847
4848 spec->mixer_nid = 0x15;
4849
4850 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
4851 alc861_models, alc861_cfg_tbl);
4852
4853 if (board_config < 0) {
4854 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4855 codec->chip_name);
4856 board_config = ALC_MODEL_AUTO;
4857 }
4858
4859 if (board_config == ALC_MODEL_AUTO) {
4860 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
4861 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4862 }
4863
4864 if (board_config == ALC_MODEL_AUTO) {
4865 /* automatic parse from the BIOS config */
4866 err = alc861_parse_auto_config(codec);
4867 if (err < 0) {
4868 alc_free(codec);
4869 return err;
4870 }
4871#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4872 else if (!err) {
4873 printk(KERN_INFO
4874 "hda_codec: Cannot set up configuration "
4875 "from BIOS. Using base mode...\n");
4876 board_config = ALC861_3ST_DIG;
4877 }
4878#endif
4879 }
4880
Takashi Iwai1d045db2011-07-07 18:23:21 +02004881 if (board_config != ALC_MODEL_AUTO)
4882 setup_preset(codec, &alc861_presets[board_config]);
4883
Takashi Iwai60a6a842011-07-27 14:01:24 +02004884 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004885 alc_auto_fill_adc_caps(codec);
4886 alc_rebuild_imux_for_auto_mic(codec);
4887 alc_remove_invalid_adc_nids(codec);
4888 }
4889
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004890 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004891 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004892
4893 if (!spec->no_analog) {
4894 err = snd_hda_attach_beep_device(codec, 0x23);
4895 if (err < 0) {
4896 alc_free(codec);
4897 return err;
4898 }
4899 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
4900 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004901
4902 spec->vmaster_nid = 0x03;
4903
4904 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4905
4906 codec->patch_ops = alc_patch_ops;
4907 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02004908 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004909#ifdef CONFIG_SND_HDA_POWER_SAVE
4910 spec->power_hook = alc_power_eapd;
4911#endif
4912 }
4913#ifdef CONFIG_SND_HDA_POWER_SAVE
4914 if (!spec->loopback.amplist)
4915 spec->loopback.amplist = alc861_loopbacks;
4916#endif
4917
4918 return 0;
4919}
4920
4921/*
4922 * ALC861-VD support
4923 *
4924 * Based on ALC882
4925 *
4926 * In addition, an independent DAC
4927 */
4928#ifdef CONFIG_SND_HDA_POWER_SAVE
4929#define alc861vd_loopbacks alc880_loopbacks
4930#endif
4931
Takashi Iwai1d045db2011-07-07 18:23:21 +02004932static int alc861vd_parse_auto_config(struct hda_codec *codec)
4933{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004934 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004935 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4936 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004937}
4938
Takashi Iwai1d045db2011-07-07 18:23:21 +02004939enum {
4940 ALC660VD_FIX_ASUS_GPIO1
4941};
4942
4943/* reset GPIO1 */
4944static const struct alc_fixup alc861vd_fixups[] = {
4945 [ALC660VD_FIX_ASUS_GPIO1] = {
4946 .type = ALC_FIXUP_VERBS,
4947 .v.verbs = (const struct hda_verb[]) {
4948 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
4949 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4950 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4951 { }
4952 }
4953 },
4954};
4955
4956static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
4957 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
4958 {}
4959};
4960
4961static const struct hda_verb alc660vd_eapd_verbs[] = {
4962 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
4963 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
4964 { }
4965};
4966
4967/*
4968 */
4969#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4970#include "alc861vd_quirks.c"
4971#endif
4972
4973static int patch_alc861vd(struct hda_codec *codec)
4974{
4975 struct alc_spec *spec;
4976 int err, board_config;
4977
4978 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4979 if (spec == NULL)
4980 return -ENOMEM;
4981
4982 codec->spec = spec;
4983
4984 spec->mixer_nid = 0x0b;
4985
4986 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
4987 alc861vd_models, alc861vd_cfg_tbl);
4988
4989 if (board_config < 0) {
4990 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4991 codec->chip_name);
4992 board_config = ALC_MODEL_AUTO;
4993 }
4994
4995 if (board_config == ALC_MODEL_AUTO) {
4996 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
4997 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4998 }
4999
5000 if (board_config == ALC_MODEL_AUTO) {
5001 /* automatic parse from the BIOS config */
5002 err = alc861vd_parse_auto_config(codec);
5003 if (err < 0) {
5004 alc_free(codec);
5005 return err;
5006 }
5007#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5008 else if (!err) {
5009 printk(KERN_INFO
5010 "hda_codec: Cannot set up configuration "
5011 "from BIOS. Using base mode...\n");
5012 board_config = ALC861VD_3ST;
5013 }
5014#endif
5015 }
5016
Takashi Iwai1d045db2011-07-07 18:23:21 +02005017 if (board_config != ALC_MODEL_AUTO)
5018 setup_preset(codec, &alc861vd_presets[board_config]);
5019
5020 if (codec->vendor_id == 0x10ec0660) {
5021 /* always turn on EAPD */
5022 add_verb(spec, alc660vd_eapd_verbs);
5023 }
5024
Takashi Iwai60a6a842011-07-27 14:01:24 +02005025 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005026 alc_auto_fill_adc_caps(codec);
5027 alc_rebuild_imux_for_auto_mic(codec);
5028 alc_remove_invalid_adc_nids(codec);
5029 }
5030
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005031 if (!spec->no_analog && !spec->cap_mixer)
5032 set_capture_mixer(codec);
5033
5034 if (!spec->no_analog) {
5035 err = snd_hda_attach_beep_device(codec, 0x23);
5036 if (err < 0) {
5037 alc_free(codec);
5038 return err;
5039 }
5040 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5041 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005042
5043 spec->vmaster_nid = 0x02;
5044
5045 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5046
5047 codec->patch_ops = alc_patch_ops;
5048
5049 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005050 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005051 spec->shutup = alc_eapd_shutup;
5052#ifdef CONFIG_SND_HDA_POWER_SAVE
5053 if (!spec->loopback.amplist)
5054 spec->loopback.amplist = alc861vd_loopbacks;
5055#endif
5056
5057 return 0;
5058}
5059
5060/*
5061 * ALC662 support
5062 *
5063 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5064 * configuration. Each pin widget can choose any input DACs and a mixer.
5065 * Each ADC is connected from a mixer of all inputs. This makes possible
5066 * 6-channel independent captures.
5067 *
5068 * In addition, an independent DAC for the multi-playback (not used in this
5069 * driver yet).
5070 */
5071#ifdef CONFIG_SND_HDA_POWER_SAVE
5072#define alc662_loopbacks alc880_loopbacks
5073#endif
5074
5075/*
5076 * BIOS auto configuration
5077 */
5078
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005079static int alc662_parse_auto_config(struct hda_codec *codec)
5080{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005081 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005082 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5083 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5084 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005085
Kailang Yang6227cdc2010-02-25 08:36:52 +01005086 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5087 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005088 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005089 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005090 ssids = alc662_ssids;
5091 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005092}
5093
Todd Broch6be79482010-12-07 16:51:05 -08005094static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005095 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005096{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005097 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005098 return;
Todd Broch6be79482010-12-07 16:51:05 -08005099 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5100 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5101 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5102 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5103 (0 << AC_AMPCAP_MUTE_SHIFT)))
5104 printk(KERN_WARNING
5105 "hda_codec: failed to override amp caps for NID 0x2\n");
5106}
5107
David Henningsson6cb3b702010-09-09 08:51:44 +02005108enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005109 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005110 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005111 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005112 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005113 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005114 ALC662_FIXUP_HP_RP5800,
David Henningsson6cb3b702010-09-09 08:51:44 +02005115};
5116
5117static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005118 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005119 .type = ALC_FIXUP_PINS,
5120 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005121 { 0x15, 0x99130112 }, /* subwoofer */
5122 { }
5123 }
5124 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005125 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005126 .type = ALC_FIXUP_PINS,
5127 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005128 { 0x17, 0x99130112 }, /* subwoofer */
5129 { }
5130 }
5131 },
Todd Broch6be79482010-12-07 16:51:05 -08005132 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005133 .type = ALC_FIXUP_FUNC,
5134 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005135 },
5136 [ALC662_FIXUP_CZC_P10T] = {
5137 .type = ALC_FIXUP_VERBS,
5138 .v.verbs = (const struct hda_verb[]) {
5139 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5140 {}
5141 }
5142 },
David Henningsson94024cd2011-04-29 14:10:55 +02005143 [ALC662_FIXUP_SKU_IGNORE] = {
5144 .type = ALC_FIXUP_SKU,
5145 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005146 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005147 [ALC662_FIXUP_HP_RP5800] = {
5148 .type = ALC_FIXUP_PINS,
5149 .v.pins = (const struct alc_pincfg[]) {
5150 { 0x14, 0x0221201f }, /* HP out */
5151 { }
5152 },
5153 .chained = true,
5154 .chain_id = ALC662_FIXUP_SKU_IGNORE
5155 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005156};
5157
Takashi Iwaia9111322011-05-02 11:30:18 +02005158static const struct snd_pci_quirk alc662_fixup_tbl[] = {
David Henningssona6c47a82011-02-10 15:39:19 +01005159 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005160 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005161 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005162 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005163 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005164 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005165 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005166 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02005167 {}
5168};
5169
Todd Broch6be79482010-12-07 16:51:05 -08005170static const struct alc_model_fixup alc662_fixup_models[] = {
5171 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
5172 {}
5173};
David Henningsson6cb3b702010-09-09 08:51:44 +02005174
5175
Takashi Iwai1d045db2011-07-07 18:23:21 +02005176/*
5177 */
5178#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5179#include "alc662_quirks.c"
5180#endif
5181
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005182static int patch_alc662(struct hda_codec *codec)
5183{
5184 struct alc_spec *spec;
5185 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02005186 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005187
5188 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5189 if (!spec)
5190 return -ENOMEM;
5191
5192 codec->spec = spec;
5193
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005194 spec->mixer_nid = 0x0b;
5195
Kailang Yangda00c242010-03-19 11:23:45 +01005196 alc_auto_parse_customize_define(codec);
5197
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005198 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5199
Kailang Yang693194f2010-10-21 08:51:48 +02005200 coef = alc_read_coef_idx(codec, 0);
5201 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005202 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005203 else if (coef & (1 << 14) &&
5204 codec->bus->pci->subsystem_vendor == 0x1025 &&
5205 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005206 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005207 else if (coef == 0x4011)
5208 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005209
Takashi Iwai1d045db2011-07-07 18:23:21 +02005210 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
5211 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005212 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005213 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5214 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005215 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005216 }
5217
Takashi Iwai1d045db2011-07-07 18:23:21 +02005218 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005219 alc_pick_fixup(codec, alc662_fixup_models,
5220 alc662_fixup_tbl, alc662_fixups);
5221 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005222 /* automatic parse from the BIOS config */
5223 err = alc662_parse_auto_config(codec);
5224 if (err < 0) {
5225 alc_free(codec);
5226 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005227 }
5228#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5229 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005230 printk(KERN_INFO
5231 "hda_codec: Cannot set up configuration "
5232 "from BIOS. Using base mode...\n");
5233 board_config = ALC662_3ST_2ch_DIG;
5234 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005235#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005236 }
5237
Takashi Iwai1d045db2011-07-07 18:23:21 +02005238 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005239 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005240
Takashi Iwai60a6a842011-07-27 14:01:24 +02005241 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005242 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005243 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005244 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005245 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005246
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005247 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005248 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005249
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005250 if (!spec->no_analog && has_cdefine_beep(codec)) {
5251 err = snd_hda_attach_beep_device(codec, 0x1);
5252 if (err < 0) {
5253 alc_free(codec);
5254 return err;
5255 }
Kailang Yangda00c242010-03-19 11:23:45 +01005256 switch (codec->vendor_id) {
5257 case 0x10ec0662:
5258 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5259 break;
5260 case 0x10ec0272:
5261 case 0x10ec0663:
5262 case 0x10ec0665:
5263 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5264 break;
5265 case 0x10ec0273:
5266 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5267 break;
5268 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005269 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005270 spec->vmaster_nid = 0x02;
5271
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005272 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5273
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005274 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005275 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005276 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c716152011-04-07 10:37:16 +02005277 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005278
Kailang Yangbf1b0222010-10-21 08:49:56 +02005279 alc_init_jacks(codec);
5280
Takashi Iwaicb53c622007-08-10 17:21:45 +02005281#ifdef CONFIG_SND_HDA_POWER_SAVE
5282 if (!spec->loopback.amplist)
5283 spec->loopback.amplist = alc662_loopbacks;
5284#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005285
5286 return 0;
5287}
5288
Kailang Yang274693f2009-12-03 10:07:50 +01005289static int patch_alc888(struct hda_codec *codec)
5290{
5291 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5292 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005293 if (codec->vendor_id == 0x10ec0887)
5294 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5295 else
5296 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005297 if (!codec->chip_name) {
5298 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005299 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005300 }
5301 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005302 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005303 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005304}
5305
Kailang Yangb478b992011-05-18 11:51:15 +02005306static int patch_alc899(struct hda_codec *codec)
5307{
5308 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5309 kfree(codec->chip_name);
5310 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5311 }
5312 return patch_alc882(codec);
5313}
5314
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005315/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005316 * ALC680 support
5317 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005318
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005319static int alc680_parse_auto_config(struct hda_codec *codec)
5320{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005321 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005322}
5323
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005324/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005325 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005326#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5327#include "alc680_quirks.c"
5328#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005329
5330static int patch_alc680(struct hda_codec *codec)
5331{
5332 struct alc_spec *spec;
5333 int board_config;
5334 int err;
5335
5336 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5337 if (spec == NULL)
5338 return -ENOMEM;
5339
5340 codec->spec = spec;
5341
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005342 /* ALC680 has no aa-loopback mixer */
5343
Takashi Iwai1d045db2011-07-07 18:23:21 +02005344 board_config = alc_board_config(codec, ALC680_MODEL_LAST,
5345 alc680_models, alc680_cfg_tbl);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005346
Takashi Iwai1d045db2011-07-07 18:23:21 +02005347 if (board_config < 0) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005348 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5349 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005350 board_config = ALC_MODEL_AUTO;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005351 }
5352
Takashi Iwai1d045db2011-07-07 18:23:21 +02005353 if (board_config == ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005354 /* automatic parse from the BIOS config */
5355 err = alc680_parse_auto_config(codec);
5356 if (err < 0) {
5357 alc_free(codec);
5358 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005359 }
5360#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5361 else if (!err) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005362 printk(KERN_INFO
5363 "hda_codec: Cannot set up configuration "
5364 "from BIOS. Using base mode...\n");
5365 board_config = ALC680_BASE;
5366 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005367#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005368 }
5369
Takashi Iwai1d045db2011-07-07 18:23:21 +02005370 if (board_config != ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005371 setup_preset(codec, &alc680_presets[board_config]);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005372#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
Takashi Iwai21268962011-07-07 15:01:13 +02005373 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005374#endif
Takashi Iwai21268962011-07-07 15:01:13 +02005375 }
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005376
Takashi Iwai60a6a842011-07-27 14:01:24 +02005377 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005378 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005379 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005380 alc_remove_invalid_adc_nids(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005381 }
5382
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005383 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005384 set_capture_mixer(codec);
5385
5386 spec->vmaster_nid = 0x02;
5387
5388 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005389 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005390 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005391
5392 return 0;
5393}
5394
5395/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396 * patch entries
5397 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005398static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005399 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005401 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005402 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005403 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005404 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005405 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005406 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005407 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005408 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005409 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005410 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005411 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5412 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5413 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005414 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005415 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005416 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5417 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005418 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005419 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005420 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005421 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005422 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02005424 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005425 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005426 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005427 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005428 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005429 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005430 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005431 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005432 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005433 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02005434 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005435 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005436 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437 {} /* terminator */
5438};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005439
5440MODULE_ALIAS("snd-hda-codec-id:10ec*");
5441
5442MODULE_LICENSE("GPL");
5443MODULE_DESCRIPTION("Realtek HD-audio codec");
5444
5445static struct hda_codec_preset_list realtek_list = {
5446 .preset = snd_hda_preset_realtek,
5447 .owner = THIS_MODULE,
5448};
5449
5450static int __init patch_realtek_init(void)
5451{
5452 return snd_hda_add_codec_preset(&realtek_list);
5453}
5454
5455static void __exit patch_realtek_exit(void)
5456{
5457 snd_hda_delete_codec_preset(&realtek_list);
5458}
5459
5460module_init(patch_realtek_init)
5461module_exit(patch_realtek_exit)