blob: 8f1bd80e60274a634961db46de1a0b8349c0d0c8 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
Takashi Iwai1d045db2011-07-07 18:23:21 +02004 * HD audio interface patch for Realtek ALC codecs
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Kailang Yangdf694da2005-12-05 19:42:22 +01006 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Takashi Iwai <tiwai@suse.de>
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01009 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020031#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "hda_codec.h"
33#include "hda_local.h"
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090034#include "hda_beep.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Takashi Iwai1d045db2011-07-07 18:23:21 +020036/* unsol event tags */
37#define ALC_FRONT_EVENT 0x01
38#define ALC_DCVOL_EVENT 0x02
39#define ALC_HP_EVENT 0x04
40#define ALC_MIC_EVENT 0x08
Takashi Iwaid4a86d82010-06-23 17:51:26 +020041
Kailang Yangdf694da2005-12-05 19:42:22 +010042/* for GPIO Poll */
43#define GPIO_MASK 0x03
44
Takashi Iwai4a79ba32009-04-22 16:31:35 +020045/* extra amp-initialization sequence types */
46enum {
47 ALC_INIT_NONE,
48 ALC_INIT_DEFAULT,
49 ALC_INIT_GPIO1,
50 ALC_INIT_GPIO2,
51 ALC_INIT_GPIO3,
52};
53
Kailang Yangda00c242010-03-19 11:23:45 +010054struct alc_customize_define {
55 unsigned int sku_cfg;
56 unsigned char port_connectivity;
57 unsigned char check_sum;
58 unsigned char customization;
59 unsigned char external_amp;
60 unsigned int enable_pcbeep:1;
61 unsigned int platform_type:1;
62 unsigned int swap:1;
63 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020064 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010065};
66
Takashi Iwaib5bfbc62011-01-13 14:22:32 +010067struct alc_fixup;
68
Takashi Iwaice764ab2011-04-27 16:35:23 +020069struct alc_multi_io {
70 hda_nid_t pin; /* multi-io widget pin NID */
71 hda_nid_t dac; /* DAC to be connected */
72 unsigned int ctl_in; /* cached input-pin control value */
73};
74
Takashi Iwaid922b512011-04-28 12:18:53 +020075enum {
Takashi Iwai3b8510c2011-04-28 14:03:24 +020076 ALC_AUTOMUTE_PIN, /* change the pin control */
77 ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
78 ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
Takashi Iwaid922b512011-04-28 12:18:53 +020079};
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081struct alc_spec {
82 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020083 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 unsigned int num_mixers;
Takashi Iwaia9111322011-05-02 11:30:18 +020085 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010086 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwai2d9c6482009-10-13 08:06:55 +020088 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +020089 * don't forget NULL
90 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +020091 */
92 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Takashi Iwaiaa563af2009-07-31 10:05:11 +020094 char stream_name_analog[32]; /* analog PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +020095 const struct hda_pcm_stream *stream_analog_playback;
96 const struct hda_pcm_stream *stream_analog_capture;
97 const struct hda_pcm_stream *stream_analog_alt_playback;
98 const struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200100 char stream_name_digital[32]; /* digital PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +0200101 const struct hda_pcm_stream *stream_digital_playback;
102 const struct hda_pcm_stream *stream_digital_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200105 struct hda_multi_out multiout; /* playback set-up
106 * max_channels, dacs must be set
107 * dig_out_nid and hp_nid are optional
108 */
Takashi Iwai63300792008-01-24 15:31:36 +0100109 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100110 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100111 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 /* capture */
114 unsigned int num_adc_nids;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +0200115 const hda_nid_t *adc_nids;
116 const hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200117 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Takashi Iwai1f0f4b82011-06-27 10:52:59 +0200118 hda_nid_t mixer_nid; /* analog-mixer NID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Takashi Iwai840b64c2010-07-13 22:49:01 +0200120 /* capture setup for dynamic dual-adc switch */
Takashi Iwai840b64c2010-07-13 22:49:01 +0200121 hda_nid_t cur_adc;
122 unsigned int cur_adc_stream_tag;
123 unsigned int cur_adc_format;
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200126 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 const struct hda_input_mux *input_mux;
128 unsigned int cur_mux[3];
Takashi Iwai21268962011-07-07 15:01:13 +0200129 hda_nid_t ext_mic_pin;
130 hda_nid_t dock_mic_pin;
131 hda_nid_t int_mic_pin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100134 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200136 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200137 int const_channel_count;
138 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100141 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200142
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200143 /* dynamic controls, init_verbs and input_mux */
144 struct auto_pin_cfg autocfg;
Kailang Yangda00c242010-03-19 11:23:45 +0100145 struct alc_customize_define cdefine;
Takashi Iwai603c4012008-07-30 15:01:44 +0200146 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200147 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200148 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai49535502009-06-30 15:28:30 +0200149 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
150 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai21268962011-07-07 15:01:13 +0200151 hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
152 unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
153 int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
Takashi Iwai834be882006-03-01 14:16:17 +0100154
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100155 /* hooks */
156 void (*init_hook)(struct hda_codec *codec);
157 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100158#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500159 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100160#endif
Takashi Iwai1c716152011-04-07 10:37:16 +0200161 void (*shutup)(struct hda_codec *codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100162
Takashi Iwai834be882006-03-01 14:16:17 +0100163 /* for pin sensing */
Takashi Iwai834be882006-03-01 14:16:17 +0100164 unsigned int jack_present: 1;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200165 unsigned int line_jack_present:1;
Takashi Iwaie9427962011-04-28 15:46:07 +0200166 unsigned int master_mute:1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200167 unsigned int auto_mic:1;
Takashi Iwai21268962011-07-07 15:01:13 +0200168 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
Takashi Iwaid922b512011-04-28 12:18:53 +0200169 unsigned int automute:1; /* HP automute enabled */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200170 unsigned int detect_line:1; /* Line-out detection enabled */
171 unsigned int automute_lines:1; /* automute line-out as well */
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200172 unsigned int automute_hp_lo:1; /* both HP and LO available */
Takashi Iwaicb53c622007-08-10 17:21:45 +0200173
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100174 /* other flags */
175 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai21268962011-07-07 15:01:13 +0200176 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai584c0c42011-03-10 12:51:11 +0100177 unsigned int single_input_src:1;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +0200178 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
Takashi Iwaid922b512011-04-28 12:18:53 +0200179
180 /* auto-mute control */
181 int automute_mode;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200182 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
Takashi Iwaid922b512011-04-28 12:18:53 +0200183
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200184 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200185 int codec_variant; /* flag for other variants */
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100186
Takashi Iwai2134ea42008-01-10 16:53:55 +0100187 /* for virtual master */
188 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200189#ifdef CONFIG_SND_HDA_POWER_SAVE
190 struct hda_loopback_check loopback;
191#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200192
193 /* for PLL fix */
194 hda_nid_t pll_nid;
195 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +0100196
197 /* fix-up list */
198 int fixup_id;
199 const struct alc_fixup *fixup_list;
200 const char *fixup_name;
Takashi Iwaice764ab2011-04-27 16:35:23 +0200201
202 /* multi-io */
203 int multi_ios;
204 struct alc_multi_io multi_io[4];
Kailang Yangdf694da2005-12-05 19:42:22 +0100205};
206
Takashi Iwai1d045db2011-07-07 18:23:21 +0200207#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Takashi Iwai44c02402011-07-08 15:14:19 +0200209static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
210 int dir, unsigned int bits)
211{
212 if (!nid)
213 return false;
214 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
215 if (query_amp_caps(codec, nid, dir) & bits)
216 return true;
217 return false;
218}
219
220#define nid_has_mute(codec, nid, dir) \
221 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
222#define nid_has_volume(codec, nid, dir) \
223 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225/*
226 * input MUX handling
227 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200228static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
229 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230{
231 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
232 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200233 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
234 if (mux_idx >= spec->num_mux_defs)
235 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100236 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
237 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200238 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200241static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
244 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
245 struct alc_spec *spec = codec->spec;
246 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
247
248 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
249 return 0;
250}
251
Takashi Iwai21268962011-07-07 15:01:13 +0200252static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253{
Takashi Iwai21268962011-07-07 15:01:13 +0200254 struct alc_spec *spec = codec->spec;
255 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
256
257 if (spec->cur_adc && spec->cur_adc != new_adc) {
258 /* stream is running, let's swap the current ADC */
259 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
260 spec->cur_adc = new_adc;
261 snd_hda_codec_setup_stream(codec, new_adc,
262 spec->cur_adc_stream_tag, 0,
263 spec->cur_adc_format);
264 return true;
265 }
266 return false;
267}
268
269/* select the given imux item; either unmute exclusively or select the route */
270static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
271 unsigned int idx, bool force)
272{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100274 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100275 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200276 int i, type;
277 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Takashi Iwaicd896c32008-11-18 12:36:33 +0100279 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
280 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100281 if (!imux->num_items && mux_idx > 0)
282 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100283
Takashi Iwai21268962011-07-07 15:01:13 +0200284 if (idx >= imux->num_items)
285 idx = imux->num_items - 1;
286 if (spec->cur_mux[adc_idx] == idx && !force)
287 return 0;
288 spec->cur_mux[adc_idx] = idx;
289
290 if (spec->dyn_adc_switch) {
291 alc_dyn_adc_pcm_resetup(codec, idx);
292 adc_idx = spec->dyn_adc_idx[idx];
293 }
294
295 nid = spec->capsrc_nids ?
296 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
297
298 /* no selection? */
299 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
300 return 1;
301
Takashi Iwaia22d5432009-07-27 12:54:26 +0200302 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200303 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100304 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100305 for (i = 0; i < imux->num_items; i++) {
306 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
307 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
308 imux->items[i].index,
309 HDA_AMP_MUTE, v);
310 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100311 } else {
312 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200313 snd_hda_codec_write_cache(codec, nid, 0,
314 AC_VERB_SET_CONNECT_SEL,
315 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100316 }
Takashi Iwai21268962011-07-07 15:01:13 +0200317 return 1;
318}
319
320static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
321 struct snd_ctl_elem_value *ucontrol)
322{
323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
324 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
325 return alc_mux_select(codec, adc_idx,
326 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100327}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100330 * set up the input pin config (depending on the given auto-pin type)
331 */
332static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
333 int auto_pin_type)
334{
335 unsigned int val = PIN_IN;
336
Takashi Iwai86e29592010-09-09 14:50:17 +0200337 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100338 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200339 unsigned int oldval;
340 oldval = snd_hda_codec_read(codec, nid, 0,
341 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100342 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100343 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200344 /* if the default pin setup is vref50, we give it priority */
345 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100346 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200347 else if (pincap & AC_PINCAP_VREF_50)
348 val = PIN_VREF50;
349 else if (pincap & AC_PINCAP_VREF_100)
350 val = PIN_VREF100;
351 else if (pincap & AC_PINCAP_VREF_GRD)
352 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100353 }
354 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
355}
356
357/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200358 * Append the given mixer and verb elements for the later use
359 * The mixer array is referred in build_controls(), and init_verbs are
360 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100361 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200362static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100363{
364 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
365 return;
366 spec->mixers[spec->num_mixers++] = mix;
367}
368
369static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
370{
371 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
372 return;
373 spec->init_verbs[spec->num_init_verbs++] = verb;
374}
375
376/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200377 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100378 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200379/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200380static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200381 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
382 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
383 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
384 { }
385};
386
Takashi Iwaia9111322011-05-02 11:30:18 +0200387static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200388 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
389 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
390 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
391 { }
392};
393
Takashi Iwaia9111322011-05-02 11:30:18 +0200394static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200395 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
396 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
397 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
398 { }
399};
400
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200401/*
402 * Fix hardware PLL issue
403 * On some codecs, the analog PLL gating control must be off while
404 * the default value is 1.
405 */
406static void alc_fix_pll(struct hda_codec *codec)
407{
408 struct alc_spec *spec = codec->spec;
409 unsigned int val;
410
411 if (!spec->pll_nid)
412 return;
413 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
414 spec->pll_coef_idx);
415 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
416 AC_VERB_GET_PROC_COEF, 0);
417 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
418 spec->pll_coef_idx);
419 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
420 val & ~(1 << spec->pll_coef_bit));
421}
422
423static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
424 unsigned int coef_idx, unsigned int coef_bit)
425{
426 struct alc_spec *spec = codec->spec;
427 spec->pll_nid = nid;
428 spec->pll_coef_idx = coef_idx;
429 spec->pll_coef_bit = coef_bit;
430 alc_fix_pll(codec);
431}
432
Takashi Iwai1d045db2011-07-07 18:23:21 +0200433/*
434 * Jack-reporting via input-jack layer
435 */
436
437/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200438static int alc_init_jacks(struct hda_codec *codec)
439{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100440#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200441 struct alc_spec *spec = codec->spec;
442 int err;
443 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200444 unsigned int mic_nid = spec->ext_mic_pin;
445 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200446
Takashi Iwai265a0242010-09-21 11:26:21 +0200447 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100448 err = snd_hda_input_jack_add(codec, hp_nid,
449 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200450 if (err < 0)
451 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100452 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200453 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200454
Takashi Iwai265a0242010-09-21 11:26:21 +0200455 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100456 err = snd_hda_input_jack_add(codec, mic_nid,
457 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200458 if (err < 0)
459 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100460 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200461 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200462 if (dock_nid) {
463 err = snd_hda_input_jack_add(codec, dock_nid,
464 SND_JACK_MICROPHONE, NULL);
465 if (err < 0)
466 return err;
467 snd_hda_input_jack_report(codec, dock_nid);
468 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100469#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200470 return 0;
471}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200472
Takashi Iwai1d045db2011-07-07 18:23:21 +0200473/*
474 * Jack detections for HP auto-mute and mic-switch
475 */
476
477/* check each pin in the given array; returns true if any of them is plugged */
478static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200479{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200480 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200481
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200482 for (i = 0; i < num_pins; i++) {
483 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200484 if (!nid)
485 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100486 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200487 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200488 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200489 return present;
490}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200491
Takashi Iwai1d045db2011-07-07 18:23:21 +0200492/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200493static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200494 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200495{
496 struct alc_spec *spec = codec->spec;
497 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200498 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200499 int i;
500
501 for (i = 0; i < num_pins; i++) {
502 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200503 if (!nid)
504 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200505 switch (spec->automute_mode) {
506 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200507 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200508 AC_VERB_SET_PIN_WIDGET_CONTROL,
509 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200510 break;
511 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200512 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200513 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200514 break;
515 case ALC_AUTOMUTE_MIXER:
516 nid = spec->automute_mixer_nid[i];
517 if (!nid)
518 break;
519 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200520 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200521 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200522 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200523 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200524 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200525 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200526}
527
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200528/* Toggle internal speakers muting */
529static void update_speakers(struct hda_codec *codec)
530{
531 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200532 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200533
Takashi Iwaic0a20262011-06-10 15:28:15 +0200534 /* Control HP pins/amps depending on master_mute state;
535 * in general, HP pins/amps control should be enabled in all cases,
536 * but currently set only for master_mute, just to be safe
537 */
538 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
539 spec->autocfg.hp_pins, spec->master_mute, true);
540
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200541 if (!spec->automute)
542 on = 0;
543 else
544 on = spec->jack_present | spec->line_jack_present;
545 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200546 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200547 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200548
549 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200550 /* if LO is a copy of either HP or Speaker, don't need to handle it */
551 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
552 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200553 return;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200554 if (!spec->automute_lines || !spec->automute)
555 on = 0;
556 else
557 on = spec->jack_present;
558 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200559 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200560 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200561}
562
Takashi Iwai1d045db2011-07-07 18:23:21 +0200563/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200564static void alc_hp_automute(struct hda_codec *codec)
565{
566 struct alc_spec *spec = codec->spec;
567
568 if (!spec->automute)
569 return;
570 spec->jack_present =
571 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
572 spec->autocfg.hp_pins);
573 update_speakers(codec);
574}
575
Takashi Iwai1d045db2011-07-07 18:23:21 +0200576/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200577static void alc_line_automute(struct hda_codec *codec)
578{
579 struct alc_spec *spec = codec->spec;
580
581 if (!spec->automute || !spec->detect_line)
582 return;
583 spec->line_jack_present =
584 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
585 spec->autocfg.line_out_pins);
586 update_speakers(codec);
587}
588
Takashi Iwai8d087c72011-06-28 12:45:47 +0200589#define get_connection_index(codec, mux, nid) \
590 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200591
Takashi Iwai1d045db2011-07-07 18:23:21 +0200592/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200593static void alc_mic_automute(struct hda_codec *codec)
594{
595 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200596 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200597
Takashi Iwai21268962011-07-07 15:01:13 +0200598 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200599 return;
600 if (snd_BUG_ON(!spec->adc_nids))
601 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200602 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200603 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200604
Takashi Iwai21268962011-07-07 15:01:13 +0200605 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
606 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
607 else if (spec->dock_mic_idx >= 0 &&
608 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
609 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
610 else
611 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200612
Takashi Iwai21268962011-07-07 15:01:13 +0200613 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
614 if (spec->dock_mic_idx >= 0)
615 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200616}
617
Kailang Yangc9b58002007-10-16 14:30:01 +0200618/* unsolicited event for HP jack sensing */
619static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
620{
621 if (codec->vendor_id == 0x10ec0880)
622 res >>= 28;
623 else
624 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200625 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200626 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200627 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200628 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200629 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200630 alc_line_automute(codec);
631 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200632 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200633 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200634 break;
635 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200636}
637
Takashi Iwai1d045db2011-07-07 18:23:21 +0200638/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200639static void alc_inithook(struct hda_codec *codec)
640{
Takashi Iwaid922b512011-04-28 12:18:53 +0200641 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200642 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200643 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200644}
645
Kailang Yangf9423e72008-05-27 12:32:25 +0200646/* additional initialization for ALC888 variants */
647static void alc888_coef_init(struct hda_codec *codec)
648{
649 unsigned int tmp;
650
651 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
652 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
653 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100654 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200655 /* alc888S-VC */
656 snd_hda_codec_read(codec, 0x20, 0,
657 AC_VERB_SET_PROC_COEF, 0x830);
658 else
659 /* alc888-VB */
660 snd_hda_codec_read(codec, 0x20, 0,
661 AC_VERB_SET_PROC_COEF, 0x3030);
662}
663
Takashi Iwai1d045db2011-07-07 18:23:21 +0200664/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200665static void alc889_coef_init(struct hda_codec *codec)
666{
667 unsigned int tmp;
668
669 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
670 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
671 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
672 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
673}
674
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100675/* turn on/off EAPD control (only if available) */
676static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
677{
678 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
679 return;
680 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
681 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
682 on ? 2 : 0);
683}
684
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200685/* turn on/off EAPD controls of the codec */
686static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
687{
688 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200689 static hda_nid_t pins[] = {
690 0x0f, 0x10, 0x14, 0x15, 0
691 };
692 hda_nid_t *p;
693 for (p = pins; *p; p++)
694 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200695}
696
Takashi Iwai1c716152011-04-07 10:37:16 +0200697/* generic shutup callback;
698 * just turning off EPAD and a little pause for avoiding pop-noise
699 */
700static void alc_eapd_shutup(struct hda_codec *codec)
701{
702 alc_auto_setup_eapd(codec, false);
703 msleep(200);
704}
705
Takashi Iwai1d045db2011-07-07 18:23:21 +0200706/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200707static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200708{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200709 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200710
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200711 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200712 switch (type) {
713 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200714 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
715 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200716 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200717 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
718 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200719 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200720 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
721 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200722 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200723 switch (codec->vendor_id) {
724 case 0x10ec0260:
725 snd_hda_codec_write(codec, 0x1a, 0,
726 AC_VERB_SET_COEF_INDEX, 7);
727 tmp = snd_hda_codec_read(codec, 0x1a, 0,
728 AC_VERB_GET_PROC_COEF, 0);
729 snd_hda_codec_write(codec, 0x1a, 0,
730 AC_VERB_SET_COEF_INDEX, 7);
731 snd_hda_codec_write(codec, 0x1a, 0,
732 AC_VERB_SET_PROC_COEF,
733 tmp | 0x2010);
734 break;
735 case 0x10ec0262:
736 case 0x10ec0880:
737 case 0x10ec0882:
738 case 0x10ec0883:
739 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100740 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100741 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200742 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200743 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200744 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200745 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200746 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100747#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200748 case 0x10ec0267:
749 case 0x10ec0268:
750 snd_hda_codec_write(codec, 0x20, 0,
751 AC_VERB_SET_COEF_INDEX, 7);
752 tmp = snd_hda_codec_read(codec, 0x20, 0,
753 AC_VERB_GET_PROC_COEF, 0);
754 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200755 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200756 snd_hda_codec_write(codec, 0x20, 0,
757 AC_VERB_SET_PROC_COEF,
758 tmp | 0x3000);
759 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100760#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200761 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200762 break;
763 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200764}
Kailang Yangea1fb292008-08-26 12:58:38 +0200765
Takashi Iwai1d045db2011-07-07 18:23:21 +0200766/*
767 * Auto-Mute mode mixer enum support
768 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200769static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
770 struct snd_ctl_elem_info *uinfo)
771{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200772 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
773 struct alc_spec *spec = codec->spec;
774 static const char * const texts2[] = {
775 "Disabled", "Enabled"
776 };
777 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200778 "Disabled", "Speaker Only", "Line-Out+Speaker"
779 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200780 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200781
782 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
783 uinfo->count = 1;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200784 if (spec->automute_hp_lo) {
785 uinfo->value.enumerated.items = 3;
786 texts = texts3;
787 } else {
788 uinfo->value.enumerated.items = 2;
789 texts = texts2;
790 }
791 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
792 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200793 strcpy(uinfo->value.enumerated.name,
794 texts[uinfo->value.enumerated.item]);
795 return 0;
796}
797
798static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
799 struct snd_ctl_elem_value *ucontrol)
800{
801 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
802 struct alc_spec *spec = codec->spec;
803 unsigned int val;
804 if (!spec->automute)
805 val = 0;
806 else if (!spec->automute_lines)
807 val = 1;
808 else
809 val = 2;
810 ucontrol->value.enumerated.item[0] = val;
811 return 0;
812}
813
814static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
815 struct snd_ctl_elem_value *ucontrol)
816{
817 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
818 struct alc_spec *spec = codec->spec;
819
820 switch (ucontrol->value.enumerated.item[0]) {
821 case 0:
822 if (!spec->automute)
823 return 0;
824 spec->automute = 0;
825 break;
826 case 1:
827 if (spec->automute && !spec->automute_lines)
828 return 0;
829 spec->automute = 1;
830 spec->automute_lines = 0;
831 break;
832 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200833 if (!spec->automute_hp_lo)
834 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200835 if (spec->automute && spec->automute_lines)
836 return 0;
837 spec->automute = 1;
838 spec->automute_lines = 1;
839 break;
840 default:
841 return -EINVAL;
842 }
843 update_speakers(codec);
844 return 1;
845}
846
Takashi Iwaia9111322011-05-02 11:30:18 +0200847static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200848 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
849 .name = "Auto-Mute Mode",
850 .info = alc_automute_mode_info,
851 .get = alc_automute_mode_get,
852 .put = alc_automute_mode_put,
853};
854
Takashi Iwai1d045db2011-07-07 18:23:21 +0200855static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
856{
857 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
858 return snd_array_new(&spec->kctls);
859}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200860
861static int alc_add_automute_mode_enum(struct hda_codec *codec)
862{
863 struct alc_spec *spec = codec->spec;
864 struct snd_kcontrol_new *knew;
865
866 knew = alc_kcontrol_new(spec);
867 if (!knew)
868 return -ENOMEM;
869 *knew = alc_automute_mode_enum;
870 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
871 if (!knew->name)
872 return -ENOMEM;
873 return 0;
874}
875
Takashi Iwai1d045db2011-07-07 18:23:21 +0200876/*
877 * Check the availability of HP/line-out auto-mute;
878 * Set up appropriately if really supported
879 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200880static void alc_init_auto_hp(struct hda_codec *codec)
881{
882 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200883 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200884 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200885 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200886
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200887 if (cfg->hp_pins[0])
888 present++;
889 if (cfg->line_out_pins[0])
890 present++;
891 if (cfg->speaker_pins[0])
892 present++;
893 if (present < 2) /* need two different output types */
894 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200895 if (present == 3)
896 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200897
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200898 if (!cfg->speaker_pins[0]) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200899 memcpy(cfg->speaker_pins, cfg->line_out_pins,
900 sizeof(cfg->speaker_pins));
901 cfg->speaker_outs = cfg->line_outs;
902 }
903
904 if (!cfg->hp_pins[0]) {
905 memcpy(cfg->hp_pins, cfg->line_out_pins,
906 sizeof(cfg->hp_pins));
907 cfg->hp_outs = cfg->line_outs;
908 }
909
910 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200911 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200912 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200913 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200914 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200915 nid);
916 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200917 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200918 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200919 spec->automute = 1;
920 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200921 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200922 if (spec->automute && cfg->line_out_pins[0] &&
923 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
924 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
925 for (i = 0; i < cfg->line_outs; i++) {
926 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200927 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200928 continue;
929 snd_printdd("realtek: Enable Line-Out auto-muting "
930 "on NID 0x%x\n", nid);
931 snd_hda_codec_write_cache(codec, nid, 0,
932 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200933 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200934 spec->detect_line = 1;
935 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200936 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200937 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200938
939 if (spec->automute) {
940 /* create a control for automute mode */
941 alc_add_automute_mode_enum(codec);
942 spec->unsol_event = alc_sku_unsol_event;
943 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200944}
945
Takashi Iwai1d045db2011-07-07 18:23:21 +0200946/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200947static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
948{
949 int i;
950 for (i = 0; i < nums; i++)
951 if (list[i] == nid)
952 return i;
953 return -1;
954}
955
Takashi Iwai1d045db2011-07-07 18:23:21 +0200956/* check whether dynamic ADC-switching is available */
957static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
958{
959 struct alc_spec *spec = codec->spec;
960 struct hda_input_mux *imux = &spec->private_imux[0];
961 int i, n, idx;
962 hda_nid_t cap, pin;
963
964 if (imux != spec->input_mux) /* no dynamic imux? */
965 return false;
966
967 for (n = 0; n < spec->num_adc_nids; n++) {
968 cap = spec->private_capsrc_nids[n];
969 for (i = 0; i < imux->num_items; i++) {
970 pin = spec->imux_pins[i];
971 if (!pin)
972 return false;
973 if (get_connection_index(codec, cap, pin) < 0)
974 break;
975 }
976 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +0200977 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +0200978 }
979
980 for (i = 0; i < imux->num_items; i++) {
981 pin = spec->imux_pins[i];
982 for (n = 0; n < spec->num_adc_nids; n++) {
983 cap = spec->private_capsrc_nids[n];
984 idx = get_connection_index(codec, cap, pin);
985 if (idx >= 0) {
986 imux->items[i].index = idx;
987 spec->dyn_adc_idx[i] = n;
988 break;
989 }
990 }
991 }
992
993 snd_printdd("realtek: enabling ADC switching\n");
994 spec->dyn_adc_switch = 1;
995 return true;
996}
Takashi Iwai21268962011-07-07 15:01:13 +0200997
998/* rebuild imux for matching with the given auto-mic pins (if not yet) */
999static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1000{
1001 struct alc_spec *spec = codec->spec;
1002 struct hda_input_mux *imux;
1003 static char * const texts[3] = {
1004 "Mic", "Internal Mic", "Dock Mic"
1005 };
1006 int i;
1007
1008 if (!spec->auto_mic)
1009 return false;
1010 imux = &spec->private_imux[0];
1011 if (spec->input_mux == imux)
1012 return true;
1013 spec->imux_pins[0] = spec->ext_mic_pin;
1014 spec->imux_pins[1] = spec->int_mic_pin;
1015 spec->imux_pins[2] = spec->dock_mic_pin;
1016 for (i = 0; i < 3; i++) {
1017 strcpy(imux->items[i].label, texts[i]);
1018 if (spec->imux_pins[i])
1019 imux->num_items = i + 1;
1020 }
1021 spec->num_mux_defs = 1;
1022 spec->input_mux = imux;
1023 return true;
1024}
1025
1026/* check whether all auto-mic pins are valid; setup indices if OK */
1027static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1028{
1029 struct alc_spec *spec = codec->spec;
1030 const struct hda_input_mux *imux;
1031
1032 if (!spec->auto_mic)
1033 return false;
1034 if (spec->auto_mic_valid_imux)
1035 return true; /* already checked */
1036
1037 /* fill up imux indices */
1038 if (!alc_check_dyn_adc_switch(codec)) {
1039 spec->auto_mic = 0;
1040 return false;
1041 }
1042
1043 imux = spec->input_mux;
1044 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1045 spec->imux_pins, imux->num_items);
1046 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1047 spec->imux_pins, imux->num_items);
1048 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1049 spec->imux_pins, imux->num_items);
1050 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1051 spec->auto_mic = 0;
1052 return false; /* no corresponding imux */
1053 }
1054
1055 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1056 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001057 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001058 if (spec->dock_mic_pin)
1059 snd_hda_codec_write_cache(codec, spec->dock_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
1063 spec->auto_mic_valid_imux = 1;
1064 spec->auto_mic = 1;
1065 return true;
1066}
1067
Takashi Iwai1d045db2011-07-07 18:23:21 +02001068/*
1069 * Check the availability of auto-mic switch;
1070 * Set up if really supported
1071 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001072static void alc_init_auto_mic(struct hda_codec *codec)
1073{
1074 struct alc_spec *spec = codec->spec;
1075 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001076 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001077 int i;
1078
Takashi Iwai21268962011-07-07 15:01:13 +02001079 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1080
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001081 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001082 for (i = 0; i < cfg->num_inputs; i++) {
1083 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001084 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001085 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001086 switch (snd_hda_get_input_pin_attr(defcfg)) {
1087 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001088 if (fixed)
1089 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001090 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1091 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001092 fixed = nid;
1093 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001094 case INPUT_PIN_ATTR_UNUSED:
1095 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001096 case INPUT_PIN_ATTR_DOCK:
1097 if (dock)
1098 return; /* already occupied */
1099 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1100 return; /* invalid type */
1101 dock = nid;
1102 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001103 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001104 if (ext)
1105 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001106 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1107 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001108 ext = nid;
1109 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001110 }
1111 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001112 if (!ext && dock) {
1113 ext = dock;
1114 dock = 0;
1115 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001116 if (!ext || !fixed)
1117 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001118 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001119 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001120 if (dock && !is_jack_detectable(codec, dock))
1121 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001122
1123 /* check imux indices */
1124 spec->ext_mic_pin = ext;
1125 spec->int_mic_pin = fixed;
1126 spec->dock_mic_pin = dock;
1127
1128 spec->auto_mic = 1;
1129 if (!alc_auto_mic_check_imux(codec))
1130 return;
1131
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001132 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1133 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001134 spec->unsol_event = alc_sku_unsol_event;
1135}
1136
Takashi Iwai1d045db2011-07-07 18:23:21 +02001137/* check the availabilities of auto-mute and auto-mic switches */
1138static void alc_auto_check_switches(struct hda_codec *codec)
1139{
1140 alc_init_auto_hp(codec);
1141 alc_init_auto_mic(codec);
1142}
1143
1144/*
1145 * Realtek SSID verification
1146 */
1147
David Henningsson90622912010-10-14 14:50:18 +02001148/* Could be any non-zero and even value. When used as fixup, tells
1149 * the driver to ignore any present sku defines.
1150 */
1151#define ALC_FIXUP_SKU_IGNORE (2)
1152
Kailang Yangda00c242010-03-19 11:23:45 +01001153static int alc_auto_parse_customize_define(struct hda_codec *codec)
1154{
1155 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001156 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001157 struct alc_spec *spec = codec->spec;
1158
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001159 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1160
David Henningsson90622912010-10-14 14:50:18 +02001161 if (spec->cdefine.fixup) {
1162 ass = spec->cdefine.sku_cfg;
1163 if (ass == ALC_FIXUP_SKU_IGNORE)
1164 return -1;
1165 goto do_sku;
1166 }
1167
Kailang Yangda00c242010-03-19 11:23:45 +01001168 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001169 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001170 goto do_sku;
1171
1172 nid = 0x1d;
1173 if (codec->vendor_id == 0x10ec0260)
1174 nid = 0x17;
1175 ass = snd_hda_codec_get_pincfg(codec, nid);
1176
1177 if (!(ass & 1)) {
1178 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1179 codec->chip_name, ass);
1180 return -1;
1181 }
1182
1183 /* check sum */
1184 tmp = 0;
1185 for (i = 1; i < 16; i++) {
1186 if ((ass >> i) & 1)
1187 tmp++;
1188 }
1189 if (((ass >> 16) & 0xf) != tmp)
1190 return -1;
1191
1192 spec->cdefine.port_connectivity = ass >> 30;
1193 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1194 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1195 spec->cdefine.customization = ass >> 8;
1196do_sku:
1197 spec->cdefine.sku_cfg = ass;
1198 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1199 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1200 spec->cdefine.swap = (ass & 0x2) >> 1;
1201 spec->cdefine.override = ass & 0x1;
1202
1203 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1204 nid, spec->cdefine.sku_cfg);
1205 snd_printd("SKU: port_connectivity=0x%x\n",
1206 spec->cdefine.port_connectivity);
1207 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1208 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1209 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1210 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1211 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1212 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1213 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1214
1215 return 0;
1216}
1217
Takashi Iwai1d045db2011-07-07 18:23:21 +02001218/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001219static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1220{
Takashi Iwai21268962011-07-07 15:01:13 +02001221 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001222}
1223
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001224/* check subsystem ID and set up device-specific initialization;
1225 * return 1 if initialized, 0 if invalid SSID
1226 */
1227/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1228 * 31 ~ 16 : Manufacture ID
1229 * 15 ~ 8 : SKU ID
1230 * 7 ~ 0 : Assembly ID
1231 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1232 */
1233static int alc_subsystem_id(struct hda_codec *codec,
1234 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001235 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001236{
1237 unsigned int ass, tmp, i;
1238 unsigned nid;
1239 struct alc_spec *spec = codec->spec;
1240
David Henningsson90622912010-10-14 14:50:18 +02001241 if (spec->cdefine.fixup) {
1242 ass = spec->cdefine.sku_cfg;
1243 if (ass == ALC_FIXUP_SKU_IGNORE)
1244 return 0;
1245 goto do_sku;
1246 }
1247
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001248 ass = codec->subsystem_id & 0xffff;
1249 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1250 goto do_sku;
1251
1252 /* invalid SSID, check the special NID pin defcfg instead */
1253 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001254 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001255 * 29~21 : reserve
1256 * 20 : PCBEEP input
1257 * 19~16 : Check sum (15:1)
1258 * 15~1 : Custom
1259 * 0 : override
1260 */
1261 nid = 0x1d;
1262 if (codec->vendor_id == 0x10ec0260)
1263 nid = 0x17;
1264 ass = snd_hda_codec_get_pincfg(codec, nid);
1265 snd_printd("realtek: No valid SSID, "
1266 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001267 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001268 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001269 return 0;
1270 if ((ass >> 30) != 1) /* no physical connection */
1271 return 0;
1272
1273 /* check sum */
1274 tmp = 0;
1275 for (i = 1; i < 16; i++) {
1276 if ((ass >> i) & 1)
1277 tmp++;
1278 }
1279 if (((ass >> 16) & 0xf) != tmp)
1280 return 0;
1281do_sku:
1282 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1283 ass & 0xffff, codec->vendor_id);
1284 /*
1285 * 0 : override
1286 * 1 : Swap Jack
1287 * 2 : 0 --> Desktop, 1 --> Laptop
1288 * 3~5 : External Amplifier control
1289 * 7~6 : Reserved
1290 */
1291 tmp = (ass & 0x38) >> 3; /* external Amp control */
1292 switch (tmp) {
1293 case 1:
1294 spec->init_amp = ALC_INIT_GPIO1;
1295 break;
1296 case 3:
1297 spec->init_amp = ALC_INIT_GPIO2;
1298 break;
1299 case 7:
1300 spec->init_amp = ALC_INIT_GPIO3;
1301 break;
1302 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001303 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001304 spec->init_amp = ALC_INIT_DEFAULT;
1305 break;
1306 }
1307
1308 /* is laptop or Desktop and enable the function "Mute internal speaker
1309 * when the external headphone out jack is plugged"
1310 */
1311 if (!(ass & 0x8000))
1312 return 1;
1313 /*
1314 * 10~8 : Jack location
1315 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1316 * 14~13: Resvered
1317 * 15 : 1 --> enable the function "Mute internal speaker
1318 * when the external headphone out jack is plugged"
1319 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001320 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001321 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001322 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1323 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001324 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001325 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001326 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001327 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001328 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001329 else if (tmp == 3)
1330 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001331 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001332 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001333 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1334 spec->autocfg.line_outs))
1335 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001336 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001337 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001338 return 1;
1339}
Kailang Yangea1fb292008-08-26 12:58:38 +02001340
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001341static void alc_ssid_check(struct hda_codec *codec,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001342 hda_nid_t porta, hda_nid_t porte,
1343 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001344{
Kailang Yang6227cdc2010-02-25 08:36:52 +01001345 if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001346 struct alc_spec *spec = codec->spec;
1347 snd_printd("realtek: "
1348 "Enable default setup for auto mode as fallback\n");
1349 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001350 }
Takashi Iwai21268962011-07-07 15:01:13 +02001351}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001352
Takashi Iwai41e41f12005-06-08 14:48:49 +02001353/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001354 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001355 */
1356
1357struct alc_pincfg {
1358 hda_nid_t nid;
1359 u32 val;
1360};
1361
Todd Broche1eb5f12010-12-06 11:19:51 -08001362struct alc_model_fixup {
1363 const int id;
1364 const char *name;
1365};
1366
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001367struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001368 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001369 bool chained;
1370 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001371 union {
1372 unsigned int sku;
1373 const struct alc_pincfg *pins;
1374 const struct hda_verb *verbs;
1375 void (*func)(struct hda_codec *codec,
1376 const struct alc_fixup *fix,
1377 int action);
1378 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001379};
1380
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001381enum {
1382 ALC_FIXUP_INVALID,
1383 ALC_FIXUP_SKU,
1384 ALC_FIXUP_PINS,
1385 ALC_FIXUP_VERBS,
1386 ALC_FIXUP_FUNC,
1387};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001388
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001389enum {
1390 ALC_FIXUP_ACT_PRE_PROBE,
1391 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001392 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001393};
1394
1395static void alc_apply_fixup(struct hda_codec *codec, int action)
1396{
1397 struct alc_spec *spec = codec->spec;
1398 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001399#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001400 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001401#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001402 int depth = 0;
1403
1404 if (!spec->fixup_list)
1405 return;
1406
1407 while (id >= 0) {
1408 const struct alc_fixup *fix = spec->fixup_list + id;
1409 const struct alc_pincfg *cfg;
1410
1411 switch (fix->type) {
1412 case ALC_FIXUP_SKU:
1413 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1414 break;;
1415 snd_printdd(KERN_INFO "hda_codec: %s: "
1416 "Apply sku override for %s\n",
1417 codec->chip_name, modelname);
1418 spec->cdefine.sku_cfg = fix->v.sku;
1419 spec->cdefine.fixup = 1;
1420 break;
1421 case ALC_FIXUP_PINS:
1422 cfg = fix->v.pins;
1423 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1424 break;
1425 snd_printdd(KERN_INFO "hda_codec: %s: "
1426 "Apply pincfg for %s\n",
1427 codec->chip_name, modelname);
1428 for (; cfg->nid; cfg++)
1429 snd_hda_codec_set_pincfg(codec, cfg->nid,
1430 cfg->val);
1431 break;
1432 case ALC_FIXUP_VERBS:
1433 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1434 break;
1435 snd_printdd(KERN_INFO "hda_codec: %s: "
1436 "Apply fix-verbs for %s\n",
1437 codec->chip_name, modelname);
1438 add_verb(codec->spec, fix->v.verbs);
1439 break;
1440 case ALC_FIXUP_FUNC:
1441 if (!fix->v.func)
1442 break;
1443 snd_printdd(KERN_INFO "hda_codec: %s: "
1444 "Apply fix-func for %s\n",
1445 codec->chip_name, modelname);
1446 fix->v.func(codec, fix, action);
1447 break;
1448 default:
1449 snd_printk(KERN_ERR "hda_codec: %s: "
1450 "Invalid fixup type %d\n",
1451 codec->chip_name, fix->type);
1452 break;
1453 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001454 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001455 break;
1456 if (++depth > 10)
1457 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001458 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001459 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001460}
1461
Todd Broche1eb5f12010-12-06 11:19:51 -08001462static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001463 const struct alc_model_fixup *models,
1464 const struct snd_pci_quirk *quirk,
1465 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001466{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001467 struct alc_spec *spec = codec->spec;
1468 int id = -1;
1469 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001470
Todd Broche1eb5f12010-12-06 11:19:51 -08001471 if (codec->modelname && models) {
1472 while (models->name) {
1473 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001474 id = models->id;
1475 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001476 break;
1477 }
1478 models++;
1479 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001480 }
1481 if (id < 0) {
1482 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1483 if (quirk) {
1484 id = quirk->value;
1485#ifdef CONFIG_SND_DEBUG_VERBOSE
1486 name = quirk->name;
1487#endif
1488 }
1489 }
1490
1491 spec->fixup_id = id;
1492 if (id >= 0) {
1493 spec->fixup_list = fixlist;
1494 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001495 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001496}
1497
Takashi Iwai1d045db2011-07-07 18:23:21 +02001498/*
1499 * COEF access helper functions
1500 */
Kailang Yang274693f2009-12-03 10:07:50 +01001501static int alc_read_coef_idx(struct hda_codec *codec,
1502 unsigned int coef_idx)
1503{
1504 unsigned int val;
1505 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1506 coef_idx);
1507 val = snd_hda_codec_read(codec, 0x20, 0,
1508 AC_VERB_GET_PROC_COEF, 0);
1509 return val;
1510}
1511
Kailang Yang977ddd62010-09-15 10:02:29 +02001512static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1513 unsigned int coef_val)
1514{
1515 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1516 coef_idx);
1517 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1518 coef_val);
1519}
1520
Takashi Iwai1d045db2011-07-07 18:23:21 +02001521/*
1522 * Digital I/O handling
1523 */
1524
Takashi Iwai757899a2010-07-30 10:48:14 +02001525/* set right pin controls for digital I/O */
1526static void alc_auto_init_digital(struct hda_codec *codec)
1527{
1528 struct alc_spec *spec = codec->spec;
1529 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001530 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001531
1532 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1533 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001534 if (!pin)
1535 continue;
1536 snd_hda_codec_write(codec, pin, 0,
1537 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1538 if (!i)
1539 dac = spec->multiout.dig_out_nid;
1540 else
1541 dac = spec->slave_dig_outs[i - 1];
1542 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1543 continue;
1544 snd_hda_codec_write(codec, dac, 0,
1545 AC_VERB_SET_AMP_GAIN_MUTE,
1546 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001547 }
1548 pin = spec->autocfg.dig_in_pin;
1549 if (pin)
1550 snd_hda_codec_write(codec, pin, 0,
1551 AC_VERB_SET_PIN_WIDGET_CONTROL,
1552 PIN_IN);
1553}
1554
1555/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1556static void alc_auto_parse_digital(struct hda_codec *codec)
1557{
1558 struct alc_spec *spec = codec->spec;
1559 int i, err;
1560 hda_nid_t dig_nid;
1561
1562 /* support multiple SPDIFs; the secondary is set up as a slave */
1563 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001564 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001565 err = snd_hda_get_connections(codec,
1566 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001567 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001568 if (err < 0)
1569 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001570 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001571 if (!i) {
1572 spec->multiout.dig_out_nid = dig_nid;
1573 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1574 } else {
1575 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1576 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1577 break;
1578 spec->slave_dig_outs[i - 1] = dig_nid;
1579 }
1580 }
1581
1582 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001583 dig_nid = codec->start_nid;
1584 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1585 unsigned int wcaps = get_wcaps(codec, dig_nid);
1586 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1587 continue;
1588 if (!(wcaps & AC_WCAP_DIGITAL))
1589 continue;
1590 if (!(wcaps & AC_WCAP_CONN_LIST))
1591 continue;
1592 err = get_connection_index(codec, dig_nid,
1593 spec->autocfg.dig_in_pin);
1594 if (err >= 0) {
1595 spec->dig_in_nid = dig_nid;
1596 break;
1597 }
1598 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001599 }
1600}
1601
Takashi Iwaif95474e2007-07-10 00:47:43 +02001602/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001603 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001604 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001605static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1606 struct snd_ctl_elem_info *uinfo)
1607{
1608 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1609 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001610 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001611 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001612
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001613 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001614 if (spec->vol_in_capsrc)
1615 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1616 else
1617 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1618 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001619 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001620 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001621 return err;
1622}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001624static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1625 unsigned int size, unsigned int __user *tlv)
1626{
1627 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1628 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001629 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001630 int err;
1631
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001632 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001633 if (spec->vol_in_capsrc)
1634 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1635 else
1636 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1637 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001638 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001639 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001640 return err;
1641}
1642
1643typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1644 struct snd_ctl_elem_value *ucontrol);
1645
1646static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1647 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001648 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001649{
1650 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1651 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001652 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001653
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001654 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001655 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001656 for (i = 0; i < spec->num_adc_nids; i++) {
1657 kcontrol->private_value =
1658 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1659 3, 0, HDA_INPUT);
1660 err = func(kcontrol, ucontrol);
1661 if (err < 0)
1662 goto error;
1663 }
1664 } else {
1665 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001666 if (spec->vol_in_capsrc)
1667 kcontrol->private_value =
1668 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1669 3, 0, HDA_OUTPUT);
1670 else
1671 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001672 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1673 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001674 err = func(kcontrol, ucontrol);
1675 }
1676 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001677 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001678 return err;
1679}
1680
1681static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1682 struct snd_ctl_elem_value *ucontrol)
1683{
1684 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001685 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001686}
1687
1688static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1689 struct snd_ctl_elem_value *ucontrol)
1690{
1691 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001692 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001693}
1694
1695/* capture mixer elements */
1696#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1697
1698static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1699 struct snd_ctl_elem_value *ucontrol)
1700{
1701 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001702 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001703}
1704
1705static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1706 struct snd_ctl_elem_value *ucontrol)
1707{
1708 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001709 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001710}
1711
Takashi Iwaia23b6882009-03-23 15:21:36 +01001712#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001713 { \
1714 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1715 .name = "Capture Switch", \
1716 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1717 .count = num, \
1718 .info = alc_cap_sw_info, \
1719 .get = alc_cap_sw_get, \
1720 .put = alc_cap_sw_put, \
1721 }, \
1722 { \
1723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1724 .name = "Capture Volume", \
1725 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1726 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1727 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1728 .count = num, \
1729 .info = alc_cap_vol_info, \
1730 .get = alc_cap_vol_get, \
1731 .put = alc_cap_vol_put, \
1732 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001733 }
1734
1735#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001736 { \
1737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1738 /* .name = "Capture Source", */ \
1739 .name = "Input Source", \
1740 .count = num, \
1741 .info = alc_mux_enum_info, \
1742 .get = alc_mux_enum_get, \
1743 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001744 }
1745
1746#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001747static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001748 _DEFINE_CAPMIX(num), \
1749 _DEFINE_CAPSRC(num), \
1750 { } /* end */ \
1751}
1752
1753#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001754static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001755 _DEFINE_CAPMIX(num), \
1756 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001757}
1758
1759/* up to three ADCs */
1760DEFINE_CAPMIX(1);
1761DEFINE_CAPMIX(2);
1762DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001763DEFINE_CAPMIX_NOSRC(1);
1764DEFINE_CAPMIX_NOSRC(2);
1765DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001766
1767/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001768 * virtual master controls
1769 */
1770
1771/*
1772 * slave controls for virtual master
1773 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001774static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001775 "Front Playback Volume",
1776 "Surround Playback Volume",
1777 "Center Playback Volume",
1778 "LFE Playback Volume",
1779 "Side Playback Volume",
1780 "Headphone Playback Volume",
1781 "Speaker Playback Volume",
1782 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001783 "Line-Out Playback Volume",
1784 NULL,
1785};
1786
Takashi Iwaiea734962011-01-17 11:29:34 +01001787static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001788 "Front Playback Switch",
1789 "Surround Playback Switch",
1790 "Center Playback Switch",
1791 "LFE Playback Switch",
1792 "Side Playback Switch",
1793 "Headphone Playback Switch",
1794 "Speaker Playback Switch",
1795 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001796 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001797 "Line-Out Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001798 NULL,
1799};
1800
1801/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001802 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001804
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001805#define NID_MAPPING (-1)
1806
1807#define SUBDEV_SPEAKER_ (0 << 6)
1808#define SUBDEV_HP_ (1 << 6)
1809#define SUBDEV_LINE_ (2 << 6)
1810#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1811#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1812#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1813
Takashi Iwai603c4012008-07-30 15:01:44 +02001814static void alc_free_kctls(struct hda_codec *codec);
1815
Takashi Iwai67d634c2009-11-16 15:35:59 +01001816#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001817/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001818static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001819 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001820 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001821 { } /* end */
1822};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001823#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001824
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825static int alc_build_controls(struct hda_codec *codec)
1826{
1827 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001828 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001829 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001830 int i, j, err;
1831 unsigned int u;
1832 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
1834 for (i = 0; i < spec->num_mixers; i++) {
1835 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1836 if (err < 0)
1837 return err;
1838 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001839 if (spec->cap_mixer) {
1840 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1841 if (err < 0)
1842 return err;
1843 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001845 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001846 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001847 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 if (err < 0)
1849 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001850 if (!spec->no_analog) {
1851 err = snd_hda_create_spdif_share_sw(codec,
1852 &spec->multiout);
1853 if (err < 0)
1854 return err;
1855 spec->multiout.share_spdif = 1;
1856 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 }
1858 if (spec->dig_in_nid) {
1859 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1860 if (err < 0)
1861 return err;
1862 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001863
Takashi Iwai67d634c2009-11-16 15:35:59 +01001864#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001865 /* create beep controls if needed */
1866 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001867 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001868 for (knew = alc_beep_mixer; knew->name; knew++) {
1869 struct snd_kcontrol *kctl;
1870 kctl = snd_ctl_new1(knew, codec);
1871 if (!kctl)
1872 return -ENOMEM;
1873 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001874 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001875 if (err < 0)
1876 return err;
1877 }
1878 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001879#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001880
Takashi Iwai2134ea42008-01-10 16:53:55 +01001881 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001882 if (!spec->no_analog &&
1883 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001884 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001885 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001886 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001887 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001888 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001889 if (err < 0)
1890 return err;
1891 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001892 if (!spec->no_analog &&
1893 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001894 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1895 NULL, alc_slave_sws);
1896 if (err < 0)
1897 return err;
1898 }
1899
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001900 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001901 if (spec->capsrc_nids || spec->adc_nids) {
1902 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1903 if (!kctl)
1904 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1905 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001906 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001907 if (!nids)
1908 nids = spec->adc_nids;
1909 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1910 if (err < 0)
1911 return err;
1912 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001913 }
1914 if (spec->cap_mixer) {
1915 const char *kname = kctl ? kctl->id.name : NULL;
1916 for (knew = spec->cap_mixer; knew->name; knew++) {
1917 if (kname && strcmp(knew->name, kname) == 0)
1918 continue;
1919 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1920 for (i = 0; kctl && i < kctl->count; i++) {
1921 err = snd_hda_add_nid(codec, kctl, i,
1922 spec->adc_nids[i]);
1923 if (err < 0)
1924 return err;
1925 }
1926 }
1927 }
1928
1929 /* other nid->control mapping */
1930 for (i = 0; i < spec->num_mixers; i++) {
1931 for (knew = spec->mixers[i]; knew->name; knew++) {
1932 if (knew->iface != NID_MAPPING)
1933 continue;
1934 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1935 if (kctl == NULL)
1936 continue;
1937 u = knew->subdevice;
1938 for (j = 0; j < 4; j++, u >>= 8) {
1939 nid = u & 0x3f;
1940 if (nid == 0)
1941 continue;
1942 switch (u & 0xc0) {
1943 case SUBDEV_SPEAKER_:
1944 nid = spec->autocfg.speaker_pins[nid];
1945 break;
1946 case SUBDEV_LINE_:
1947 nid = spec->autocfg.line_out_pins[nid];
1948 break;
1949 case SUBDEV_HP_:
1950 nid = spec->autocfg.hp_pins[nid];
1951 break;
1952 default:
1953 continue;
1954 }
1955 err = snd_hda_add_nid(codec, kctl, 0, nid);
1956 if (err < 0)
1957 return err;
1958 }
1959 u = knew->private_value;
1960 for (j = 0; j < 4; j++, u >>= 8) {
1961 nid = u & 0xff;
1962 if (nid == 0)
1963 continue;
1964 err = snd_hda_add_nid(codec, kctl, 0, nid);
1965 if (err < 0)
1966 return err;
1967 }
1968 }
1969 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001970
1971 alc_free_kctls(codec); /* no longer needed */
1972
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 return 0;
1974}
1975
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001976
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001978 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001979 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001980
Takashi Iwai584c0c42011-03-10 12:51:11 +01001981static void alc_init_special_input_src(struct hda_codec *codec);
1982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983static int alc_init(struct hda_codec *codec)
1984{
1985 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001986 unsigned int i;
1987
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001988 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001989 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001990
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001991 for (i = 0; i < spec->num_init_verbs; i++)
1992 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01001993 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001994
1995 if (spec->init_hook)
1996 spec->init_hook(codec);
1997
Takashi Iwai58701122011-01-13 15:41:45 +01001998 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
1999
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002000 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 return 0;
2002}
2003
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002004static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2005{
2006 struct alc_spec *spec = codec->spec;
2007
2008 if (spec->unsol_event)
2009 spec->unsol_event(codec, res);
2010}
2011
Takashi Iwaicb53c622007-08-10 17:21:45 +02002012#ifdef CONFIG_SND_HDA_POWER_SAVE
2013static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2014{
2015 struct alc_spec *spec = codec->spec;
2016 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2017}
2018#endif
2019
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020/*
2021 * Analog playback callbacks
2022 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002023static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002025 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026{
2027 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002028 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2029 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030}
2031
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002032static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 struct hda_codec *codec,
2034 unsigned int stream_tag,
2035 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002036 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037{
2038 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002039 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2040 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041}
2042
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002043static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002045 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046{
2047 struct alc_spec *spec = codec->spec;
2048 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2049}
2050
2051/*
2052 * Digital out
2053 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002054static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002056 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057{
2058 struct alc_spec *spec = codec->spec;
2059 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2060}
2061
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002062static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002063 struct hda_codec *codec,
2064 unsigned int stream_tag,
2065 unsigned int format,
2066 struct snd_pcm_substream *substream)
2067{
2068 struct alc_spec *spec = codec->spec;
2069 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2070 stream_tag, format, substream);
2071}
2072
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002073static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002074 struct hda_codec *codec,
2075 struct snd_pcm_substream *substream)
2076{
2077 struct alc_spec *spec = codec->spec;
2078 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2079}
2080
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002081static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002083 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084{
2085 struct alc_spec *spec = codec->spec;
2086 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2087}
2088
2089/*
2090 * Analog capture
2091 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002092static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 struct hda_codec *codec,
2094 unsigned int stream_tag,
2095 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002096 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097{
2098 struct alc_spec *spec = codec->spec;
2099
Takashi Iwai63300792008-01-24 15:31:36 +01002100 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 stream_tag, 0, format);
2102 return 0;
2103}
2104
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002105static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002107 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108{
2109 struct alc_spec *spec = codec->spec;
2110
Takashi Iwai888afa12008-03-18 09:57:50 +01002111 snd_hda_codec_cleanup_stream(codec,
2112 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 return 0;
2114}
2115
Takashi Iwai840b64c2010-07-13 22:49:01 +02002116/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002117static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002118 struct hda_codec *codec,
2119 unsigned int stream_tag,
2120 unsigned int format,
2121 struct snd_pcm_substream *substream)
2122{
2123 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002124 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002125 spec->cur_adc_stream_tag = stream_tag;
2126 spec->cur_adc_format = format;
2127 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2128 return 0;
2129}
2130
Takashi Iwai21268962011-07-07 15:01:13 +02002131static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002132 struct hda_codec *codec,
2133 struct snd_pcm_substream *substream)
2134{
2135 struct alc_spec *spec = codec->spec;
2136 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2137 spec->cur_adc = 0;
2138 return 0;
2139}
2140
Takashi Iwai21268962011-07-07 15:01:13 +02002141static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002142 .substreams = 1,
2143 .channels_min = 2,
2144 .channels_max = 2,
2145 .nid = 0, /* fill later */
2146 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002147 .prepare = dyn_adc_capture_pcm_prepare,
2148 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002149 },
2150};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
2152/*
2153 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002154static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 .substreams = 1,
2156 .channels_min = 2,
2157 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002158 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002160 .open = alc_playback_pcm_open,
2161 .prepare = alc_playback_pcm_prepare,
2162 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 },
2164};
2165
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002166static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002167 .substreams = 1,
2168 .channels_min = 2,
2169 .channels_max = 2,
2170 /* NID is set in alc_build_pcms */
2171};
2172
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002173static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002174 .substreams = 1,
2175 .channels_min = 2,
2176 .channels_max = 2,
2177 /* NID is set in alc_build_pcms */
2178};
2179
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002180static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002181 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 .channels_min = 2,
2183 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002184 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002186 .prepare = alc_alt_capture_pcm_prepare,
2187 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 },
2189};
2190
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002191static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 .substreams = 1,
2193 .channels_min = 2,
2194 .channels_max = 2,
2195 /* NID is set in alc_build_pcms */
2196 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002197 .open = alc_dig_playback_pcm_open,
2198 .close = alc_dig_playback_pcm_close,
2199 .prepare = alc_dig_playback_pcm_prepare,
2200 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 },
2202};
2203
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002204static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 .substreams = 1,
2206 .channels_min = 2,
2207 .channels_max = 2,
2208 /* NID is set in alc_build_pcms */
2209};
2210
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002211/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002212static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002213 .substreams = 0,
2214 .channels_min = 0,
2215 .channels_max = 0,
2216};
2217
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218static int alc_build_pcms(struct hda_codec *codec)
2219{
2220 struct alc_spec *spec = codec->spec;
2221 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002222 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 int i;
2224
2225 codec->num_pcms = 1;
2226 codec->pcm_info = info;
2227
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002228 if (spec->no_analog)
2229 goto skip_analog;
2230
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002231 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2232 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002234
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002235 if (spec->multiout.dac_nids > 0) {
2236 p = spec->stream_analog_playback;
2237 if (!p)
2238 p = &alc_pcm_analog_playback;
2239 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002240 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2241 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002242 if (spec->adc_nids) {
2243 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002244 if (!p) {
2245 if (spec->dyn_adc_switch)
2246 p = &dyn_adc_pcm_analog_capture;
2247 else
2248 p = &alc_pcm_analog_capture;
2249 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002250 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002251 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
Takashi Iwai4a471b72005-12-07 13:56:29 +01002254 if (spec->channel_mode) {
2255 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2256 for (i = 0; i < spec->num_channel_mode; i++) {
2257 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2258 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2259 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 }
2261 }
2262
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002263 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002264 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002266 snprintf(spec->stream_name_digital,
2267 sizeof(spec->stream_name_digital),
2268 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002269 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002270 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002271 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002273 if (spec->dig_out_type)
2274 info->pcm_type = spec->dig_out_type;
2275 else
2276 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002277 if (spec->multiout.dig_out_nid) {
2278 p = spec->stream_digital_playback;
2279 if (!p)
2280 p = &alc_pcm_digital_playback;
2281 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2283 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002284 if (spec->dig_in_nid) {
2285 p = spec->stream_digital_capture;
2286 if (!p)
2287 p = &alc_pcm_digital_capture;
2288 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2290 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002291 /* FIXME: do we need this for all Realtek codec models? */
2292 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 }
2294
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002295 if (spec->no_analog)
2296 return 0;
2297
Takashi Iwaie08a0072006-09-07 17:52:14 +02002298 /* If the use of more than one ADC is requested for the current
2299 * model, configure a second analog capture-only PCM.
2300 */
2301 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002302 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002303 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002304 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002305 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002306 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002307 p = spec->stream_analog_alt_playback;
2308 if (!p)
2309 p = &alc_pcm_analog_alt_playback;
2310 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002311 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2312 spec->alt_dac_nid;
2313 } else {
2314 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2315 alc_pcm_null_stream;
2316 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2317 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002318 if (spec->num_adc_nids > 1) {
2319 p = spec->stream_analog_alt_capture;
2320 if (!p)
2321 p = &alc_pcm_analog_alt_capture;
2322 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002323 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2324 spec->adc_nids[1];
2325 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2326 spec->num_adc_nids - 1;
2327 } else {
2328 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2329 alc_pcm_null_stream;
2330 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002331 }
2332 }
2333
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 return 0;
2335}
2336
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002337static inline void alc_shutup(struct hda_codec *codec)
2338{
Takashi Iwai1c716152011-04-07 10:37:16 +02002339 struct alc_spec *spec = codec->spec;
2340
2341 if (spec && spec->shutup)
2342 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002343 snd_hda_shutup_pins(codec);
2344}
2345
Takashi Iwai603c4012008-07-30 15:01:44 +02002346static void alc_free_kctls(struct hda_codec *codec)
2347{
2348 struct alc_spec *spec = codec->spec;
2349
2350 if (spec->kctls.list) {
2351 struct snd_kcontrol_new *kctl = spec->kctls.list;
2352 int i;
2353 for (i = 0; i < spec->kctls.used; i++)
2354 kfree(kctl[i].name);
2355 }
2356 snd_array_free(&spec->kctls);
2357}
2358
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359static void alc_free(struct hda_codec *codec)
2360{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002361 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002362
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002363 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002364 return;
2365
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002366 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002367 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002368 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002369 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002370 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371}
2372
Hector Martinf5de24b2009-12-20 22:51:31 +01002373#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002374static void alc_power_eapd(struct hda_codec *codec)
2375{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002376 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002377}
2378
Hector Martinf5de24b2009-12-20 22:51:31 +01002379static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2380{
2381 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002382 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002383 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002384 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002385 return 0;
2386}
2387#endif
2388
Takashi Iwaie044c392008-10-27 16:56:24 +01002389#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaie044c392008-10-27 16:56:24 +01002390static int alc_resume(struct hda_codec *codec)
2391{
Takashi Iwai1c716152011-04-07 10:37:16 +02002392 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002393 codec->patch_ops.init(codec);
2394 snd_hda_codec_resume_amp(codec);
2395 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002396 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002397 return 0;
2398}
Takashi Iwaie044c392008-10-27 16:56:24 +01002399#endif
2400
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401/*
2402 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002403static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 .build_controls = alc_build_controls,
2405 .build_pcms = alc_build_pcms,
2406 .init = alc_init,
2407 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002408 .unsol_event = alc_unsol_event,
Takashi Iwaie044c392008-10-27 16:56:24 +01002409#ifdef SND_HDA_NEEDS_RESUME
2410 .resume = alc_resume,
2411#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002412#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002413 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002414 .check_power_status = alc_check_power_status,
2415#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002416 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417};
2418
Kailang Yangc027ddc2010-03-19 11:33:06 +01002419/* replace the codec chip_name with the given string */
2420static int alc_codec_rename(struct hda_codec *codec, const char *name)
2421{
2422 kfree(codec->chip_name);
2423 codec->chip_name = kstrdup(name, GFP_KERNEL);
2424 if (!codec->chip_name) {
2425 alc_free(codec);
2426 return -ENOMEM;
2427 }
2428 return 0;
2429}
2430
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002431/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002432 * Automatic parse of I/O pins from the BIOS configuration
2433 */
2434
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002435enum {
2436 ALC_CTL_WIDGET_VOL,
2437 ALC_CTL_WIDGET_MUTE,
2438 ALC_CTL_BIND_MUTE,
2439};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002440static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002441 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2442 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002443 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002444};
2445
2446/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002447static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002448 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002449{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002450 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002451
Takashi Iwaice764ab2011-04-27 16:35:23 +02002452 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002453 if (!knew)
2454 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002455 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002456 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002457 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002458 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002459 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002460 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002461 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002462 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002463 return 0;
2464}
2465
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002466static int add_control_with_pfx(struct alc_spec *spec, int type,
2467 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002468 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002469{
2470 char name[32];
2471 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002472 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002473}
2474
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002475#define add_pb_vol_ctrl(spec, type, pfx, val) \
2476 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2477#define add_pb_sw_ctrl(spec, type, pfx, val) \
2478 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2479#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2480 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2481#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2482 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002483
Takashi Iwai6843ca12011-06-24 11:03:58 +02002484static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2485 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002486{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002487 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002488 static const char * const chname[4] = {
2489 "Front", "Surround", NULL /*CLFE*/, "Side"
2490 };
Takashi Iwaice764ab2011-04-27 16:35:23 +02002491
Takashi Iwai6843ca12011-06-24 11:03:58 +02002492 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002493 if (cfg->line_outs == 1 && !spec->multi_ios &&
2494 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002495 return "Master";
2496
2497 switch (cfg->line_out_type) {
2498 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002499 if (cfg->line_outs == 1)
2500 return "Speaker";
2501 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002502 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002503 /* for multi-io case, only the primary out */
2504 if (ch && spec->multi_ios)
2505 break;
2506 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002507 return "Headphone";
2508 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002509 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002510 return "PCM";
2511 break;
2512 }
Takashi Iwai6843ca12011-06-24 11:03:58 +02002513 return chname[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002514}
2515
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002516/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002517static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002518 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002519 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002520{
Kailang Yangdf694da2005-12-05 19:42:22 +01002521 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002522
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002523 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002524 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2525 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002526 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002527 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002528 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2529 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002530 return err;
2531 return 0;
2532}
2533
Takashi Iwai05f5f472009-08-25 13:10:18 +02002534static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002535{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002536 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2537 return (pincap & AC_PINCAP_IN) != 0;
2538}
2539
Takashi Iwai1d045db2011-07-07 18:23:21 +02002540/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002541static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002542{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002543 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002544 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002545 hda_nid_t *adc_nids = spec->private_adc_nids;
2546 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2547 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2548 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002549 int i, nums = 0;
2550
2551 nid = codec->start_nid;
2552 for (i = 0; i < codec->num_nodes; i++, nid++) {
2553 hda_nid_t src;
2554 const hda_nid_t *list;
2555 unsigned int caps = get_wcaps(codec, nid);
2556 int type = get_wcaps_type(caps);
2557
2558 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2559 continue;
2560 adc_nids[nums] = nid;
2561 cap_nids[nums] = nid;
2562 src = nid;
2563 for (;;) {
2564 int n;
2565 type = get_wcaps_type(get_wcaps(codec, src));
2566 if (type == AC_WID_PIN)
2567 break;
2568 if (type == AC_WID_AUD_SEL) {
2569 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002570 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002571 break;
2572 }
2573 n = snd_hda_get_conn_list(codec, src, &list);
2574 if (n > 1) {
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 } else if (n != 1)
2579 break;
2580 src = *list;
2581 }
2582 if (++nums >= max_nums)
2583 break;
2584 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002585 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002586 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002587 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002588 return nums;
2589}
2590
Takashi Iwai05f5f472009-08-25 13:10:18 +02002591/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002592static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002593{
2594 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002595 const struct auto_pin_cfg *cfg = &spec->autocfg;
2596 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002597 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002598 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002599 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002600 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002601
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002602 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002603 if (num_adcs < 0)
2604 return 0;
2605
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002606 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002607 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002608 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002609
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002610 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002611 if (!alc_is_input_pin(codec, pin))
2612 continue;
2613
David Henningsson5322bf22011-01-05 11:03:56 +01002614 label = hda_get_autocfg_input_label(codec, cfg, i);
2615 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002616 type_idx++;
2617 else
2618 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002619 prev_label = label;
2620
Takashi Iwai05f5f472009-08-25 13:10:18 +02002621 if (mixer) {
2622 idx = get_connection_index(codec, mixer, pin);
2623 if (idx >= 0) {
2624 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002625 label, type_idx,
2626 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002627 if (err < 0)
2628 return err;
2629 }
2630 }
2631
Takashi Iwaib7821702011-07-06 15:12:46 +02002632 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002633 hda_nid_t cap = spec->capsrc_nids ?
2634 spec->capsrc_nids[c] : spec->adc_nids[c];
2635 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002636 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002637 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002638 snd_hda_add_imux_item(imux, label, idx, NULL);
2639 break;
2640 }
2641 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002642 }
Takashi Iwai21268962011-07-07 15:01:13 +02002643
2644 spec->num_mux_defs = 1;
2645 spec->input_mux = imux;
2646
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002647 return 0;
2648}
2649
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002650static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2651 unsigned int pin_type)
2652{
2653 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2654 pin_type);
2655 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002656 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2657 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002658 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002659}
2660
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002661static int get_pin_type(int line_out_type)
2662{
2663 if (line_out_type == AUTO_PIN_HP_OUT)
2664 return PIN_HP;
2665 else
2666 return PIN_OUT;
2667}
2668
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002669static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002670{
2671 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002672 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002673 int i;
2674
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002675 for (i = 0; i < cfg->num_inputs; i++) {
2676 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002677 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002678 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002679 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002680 snd_hda_codec_write(codec, nid, 0,
2681 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002682 AMP_OUT_MUTE);
2683 }
2684 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002685
2686 /* mute all loopback inputs */
2687 if (spec->mixer_nid) {
2688 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2689 for (i = 0; i < nums; i++)
2690 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2691 AC_VERB_SET_AMP_GAIN_MUTE,
2692 AMP_IN_MUTE(i));
2693 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002694}
2695
Takashi Iwai7085ec12009-10-02 09:03:58 +02002696/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002697static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002698{
Takashi Iwai604401a2011-04-27 15:14:23 +02002699 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002700 int i, num;
2701
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002702 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2703 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002704 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2705 for (i = 0; i < num; i++) {
2706 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2707 return list[i];
2708 }
2709 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002710}
2711
Takashi Iwai604401a2011-04-27 15:14:23 +02002712/* go down to the selector widget before the mixer */
2713static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2714{
2715 hda_nid_t srcs[5];
2716 int num = snd_hda_get_connections(codec, pin, srcs,
2717 ARRAY_SIZE(srcs));
2718 if (num != 1 ||
2719 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2720 return pin;
2721 return srcs[0];
2722}
2723
Takashi Iwai7085ec12009-10-02 09:03:58 +02002724/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002725static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002726 hda_nid_t dac)
2727{
David Henningssoncc1c4522010-11-24 14:17:47 +01002728 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002729 int i, num;
2730
Takashi Iwai604401a2011-04-27 15:14:23 +02002731 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002732 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2733 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002734 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002735 return mix[i];
2736 }
2737 return 0;
2738}
2739
Takashi Iwaice764ab2011-04-27 16:35:23 +02002740/* select the connection from pin to DAC if needed */
2741static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2742 hda_nid_t dac)
2743{
2744 hda_nid_t mix[5];
2745 int i, num;
2746
2747 pin = alc_go_down_to_selector(codec, pin);
2748 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2749 if (num < 2)
2750 return 0;
2751 for (i = 0; i < num; i++) {
2752 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2753 snd_hda_codec_update_cache(codec, pin, 0,
2754 AC_VERB_SET_CONNECT_SEL, i);
2755 return 0;
2756 }
2757 }
2758 return 0;
2759}
2760
Takashi Iwai7085ec12009-10-02 09:03:58 +02002761/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002762static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002763{
2764 struct alc_spec *spec = codec->spec;
2765 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002766 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002767
Takashi Iwai604401a2011-04-27 15:14:23 +02002768 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002769 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002770 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002771 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002772 if (!nid)
2773 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002774 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2775 spec->multiout.num_dacs))
2776 continue;
2777 if (spec->multiout.hp_nid == nid)
2778 continue;
2779 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2780 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2781 continue;
2782 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002783 }
2784 return 0;
2785}
2786
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002787static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2788{
2789 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2790 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2791 return alc_auto_look_for_dac(codec, pin);
2792 return 0;
2793}
2794
Takashi Iwai7085ec12009-10-02 09:03:58 +02002795/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002796static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002797{
2798 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002799 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002800 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002801 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002802
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002803 again:
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02002804 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002805 spec->multiout.hp_nid = 0;
2806 spec->multiout.extra_out_nid[0] = 0;
2807 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2808 spec->multiout.dac_nids = spec->private_dac_nids;
2809
2810 /* fill hard-wired DACs first */
2811 if (!redone) {
2812 for (i = 0; i < cfg->line_outs; i++)
2813 spec->private_dac_nids[i] =
2814 get_dac_if_single(codec, cfg->line_out_pins[i]);
2815 if (cfg->hp_outs)
2816 spec->multiout.hp_nid =
2817 get_dac_if_single(codec, cfg->hp_pins[0]);
2818 if (cfg->speaker_outs)
2819 spec->multiout.extra_out_nid[0] =
2820 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002821 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002822
2823 for (i = 0; i < cfg->line_outs; i++) {
2824 hda_nid_t pin = cfg->line_out_pins[i];
2825 if (spec->private_dac_nids[i])
2826 continue;
2827 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2828 if (!spec->private_dac_nids[i] && !redone) {
2829 /* if we can't find primary DACs, re-probe without
2830 * checking the hard-wired DACs
2831 */
2832 redone = true;
2833 goto again;
2834 }
2835 }
2836
2837 for (i = 0; i < cfg->line_outs; i++) {
2838 if (spec->private_dac_nids[i])
2839 spec->multiout.num_dacs++;
2840 else
2841 memmove(spec->private_dac_nids + i,
2842 spec->private_dac_nids + i + 1,
2843 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2844 }
2845
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002846 if (cfg->hp_outs && !spec->multiout.hp_nid)
2847 spec->multiout.hp_nid =
2848 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2849 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2850 spec->multiout.extra_out_nid[0] =
2851 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2852
Takashi Iwai7085ec12009-10-02 09:03:58 +02002853 return 0;
2854}
2855
Takashi Iwai343a04b2011-07-06 14:28:39 +02002856static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002857 const char *pfx, int cidx,
2858 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002859{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002860 if (!nid)
2861 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002862 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2863 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002864}
2865
Takashi Iwai343a04b2011-07-06 14:28:39 +02002866#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2867 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002868
2869/* create a mute-switch for the given mixer widget;
2870 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2871 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002872static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002873 const char *pfx, int cidx,
2874 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002875{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002876 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002877 int type;
2878 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002879 if (!nid)
2880 return 0;
2881 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2882 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2883 type = ALC_CTL_WIDGET_MUTE;
2884 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2885 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002886 type = ALC_CTL_WIDGET_MUTE;
2887 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2888 } else {
2889 type = ALC_CTL_BIND_MUTE;
2890 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2891 }
2892 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002893}
2894
Takashi Iwai343a04b2011-07-06 14:28:39 +02002895#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2896 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002897
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002898static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2899 hda_nid_t pin, hda_nid_t dac)
2900{
2901 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2902 if (nid_has_mute(codec, pin, HDA_OUTPUT))
2903 return pin;
2904 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
2905 return mix;
2906 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
2907 return dac;
2908 return 0;
2909}
2910
2911static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
2912 hda_nid_t pin, hda_nid_t dac)
2913{
2914 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2915 if (nid_has_volume(codec, dac, HDA_OUTPUT))
2916 return dac;
2917 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
2918 return mix;
2919 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
2920 return pin;
2921 return 0;
2922}
2923
Takashi Iwai7085ec12009-10-02 09:03:58 +02002924/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002925static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002926 const struct auto_pin_cfg *cfg)
2927{
2928 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002929 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002930
Takashi Iwaice764ab2011-04-27 16:35:23 +02002931 noutputs = cfg->line_outs;
2932 if (spec->multi_ios > 0)
2933 noutputs += spec->multi_ios;
2934
2935 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002936 const char *name;
2937 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002938 hda_nid_t dac, pin;
2939 hda_nid_t sw, vol;
2940
2941 dac = spec->multiout.dac_nids[i];
2942 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002943 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002944 if (i >= cfg->line_outs)
2945 pin = spec->multi_io[i - 1].pin;
2946 else
2947 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002948
2949 sw = alc_look_for_out_mute_nid(codec, pin, dac);
2950 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02002951 name = alc_get_line_out_pfx(spec, i, true, &index);
2952 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002953 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002954 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002955 if (err < 0)
2956 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002957 err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002958 if (err < 0)
2959 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002960 err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002961 if (err < 0)
2962 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002963 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002964 if (err < 0)
2965 return err;
2966 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002967 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002968 if (err < 0)
2969 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002970 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002971 if (err < 0)
2972 return err;
2973 }
2974 }
2975 return 0;
2976}
2977
2978/* add playback controls for speaker and HP outputs */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002979static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002980 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002981{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002982 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002983 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002984 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002985
2986 if (!pin)
2987 return 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002988 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02002989 /* the corresponding DAC is already occupied */
2990 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
2991 return 0; /* no way */
2992 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002993 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002994 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
2995 }
2996
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002997 sw = alc_look_for_out_mute_nid(codec, pin, dac);
2998 vol = alc_look_for_out_vol_nid(codec, pin, dac);
2999 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003000 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003001 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003002 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003003 if (err < 0)
3004 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003005 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003006}
3007
Takashi Iwai343a04b2011-07-06 14:28:39 +02003008static int alc_auto_create_hp_out(struct hda_codec *codec)
3009{
3010 struct alc_spec *spec = codec->spec;
3011 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3012 spec->multiout.hp_nid,
3013 "Headphone");
3014}
3015
3016static int alc_auto_create_speaker_out(struct hda_codec *codec)
3017{
3018 struct alc_spec *spec = codec->spec;
3019 return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
3020 spec->multiout.extra_out_nid[0],
3021 "Speaker");
3022}
3023
Takashi Iwai343a04b2011-07-06 14:28:39 +02003024static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003025 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003026 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003027{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003028 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003029 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003030 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003031
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003032 alc_set_pin_output(codec, pin, pin_type);
3033 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003034 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003035 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003036 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003037 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003038 mix = srcs[i];
3039 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003040 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003041 if (!mix)
3042 return;
3043
3044 /* need the manual connection? */
3045 if (num > 1)
3046 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3047 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003048 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3049 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003050 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003051 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003052 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003053 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003054 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003055 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3056 if (nid)
3057 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3058 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003059}
3060
Takashi Iwai343a04b2011-07-06 14:28:39 +02003061static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003062{
3063 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003064 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003065 int i;
3066
3067 for (i = 0; i <= HDA_SIDE; i++) {
3068 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3069 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003070 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003071 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003072 }
3073}
3074
Takashi Iwai343a04b2011-07-06 14:28:39 +02003075static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003076{
3077 struct alc_spec *spec = codec->spec;
3078 hda_nid_t pin;
3079
3080 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003081 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003082 alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003083 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003084 pin = spec->autocfg.speaker_pins[0];
3085 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003086 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003087 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003088}
3089
Takashi Iwaice764ab2011-04-27 16:35:23 +02003090/*
3091 * multi-io helper
3092 */
3093static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3094 unsigned int location)
3095{
3096 struct alc_spec *spec = codec->spec;
3097 struct auto_pin_cfg *cfg = &spec->autocfg;
3098 int type, i, num_pins = 0;
3099
3100 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3101 for (i = 0; i < cfg->num_inputs; i++) {
3102 hda_nid_t nid = cfg->inputs[i].pin;
3103 hda_nid_t dac;
3104 unsigned int defcfg, caps;
3105 if (cfg->inputs[i].type != type)
3106 continue;
3107 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3108 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3109 continue;
3110 if (location && get_defcfg_location(defcfg) != location)
3111 continue;
3112 caps = snd_hda_query_pin_caps(codec, nid);
3113 if (!(caps & AC_PINCAP_OUT))
3114 continue;
3115 dac = alc_auto_look_for_dac(codec, nid);
3116 if (!dac)
3117 continue;
3118 spec->multi_io[num_pins].pin = nid;
3119 spec->multi_io[num_pins].dac = dac;
3120 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003121 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003122 }
3123 }
3124 spec->multiout.num_dacs = 1;
3125 if (num_pins < 2)
3126 return 0;
3127 return num_pins;
3128}
3129
3130static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3131 struct snd_ctl_elem_info *uinfo)
3132{
3133 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3134 struct alc_spec *spec = codec->spec;
3135
3136 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3137 uinfo->count = 1;
3138 uinfo->value.enumerated.items = spec->multi_ios + 1;
3139 if (uinfo->value.enumerated.item > spec->multi_ios)
3140 uinfo->value.enumerated.item = spec->multi_ios;
3141 sprintf(uinfo->value.enumerated.name, "%dch",
3142 (uinfo->value.enumerated.item + 1) * 2);
3143 return 0;
3144}
3145
3146static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3147 struct snd_ctl_elem_value *ucontrol)
3148{
3149 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3150 struct alc_spec *spec = codec->spec;
3151 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3152 return 0;
3153}
3154
3155static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3156{
3157 struct alc_spec *spec = codec->spec;
3158 hda_nid_t nid = spec->multi_io[idx].pin;
3159
3160 if (!spec->multi_io[idx].ctl_in)
3161 spec->multi_io[idx].ctl_in =
3162 snd_hda_codec_read(codec, nid, 0,
3163 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3164 if (output) {
3165 snd_hda_codec_update_cache(codec, nid, 0,
3166 AC_VERB_SET_PIN_WIDGET_CONTROL,
3167 PIN_OUT);
3168 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3169 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3170 HDA_AMP_MUTE, 0);
3171 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3172 } else {
3173 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3174 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3175 HDA_AMP_MUTE, HDA_AMP_MUTE);
3176 snd_hda_codec_update_cache(codec, nid, 0,
3177 AC_VERB_SET_PIN_WIDGET_CONTROL,
3178 spec->multi_io[idx].ctl_in);
3179 }
3180 return 0;
3181}
3182
3183static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3184 struct snd_ctl_elem_value *ucontrol)
3185{
3186 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3187 struct alc_spec *spec = codec->spec;
3188 int i, ch;
3189
3190 ch = ucontrol->value.enumerated.item[0];
3191 if (ch < 0 || ch > spec->multi_ios)
3192 return -EINVAL;
3193 if (ch == (spec->ext_channel_count - 1) / 2)
3194 return 0;
3195 spec->ext_channel_count = (ch + 1) * 2;
3196 for (i = 0; i < spec->multi_ios; i++)
3197 alc_set_multi_io(codec, i, i < ch);
3198 spec->multiout.max_channels = spec->ext_channel_count;
3199 return 1;
3200}
3201
Takashi Iwaia9111322011-05-02 11:30:18 +02003202static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003203 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3204 .name = "Channel Mode",
3205 .info = alc_auto_ch_mode_info,
3206 .get = alc_auto_ch_mode_get,
3207 .put = alc_auto_ch_mode_put,
3208};
3209
Takashi Iwaicb053a82011-06-27 11:32:07 +02003210static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
3211 int (*fill_dac)(struct hda_codec *))
Takashi Iwaice764ab2011-04-27 16:35:23 +02003212{
3213 struct alc_spec *spec = codec->spec;
3214 struct auto_pin_cfg *cfg = &spec->autocfg;
3215 unsigned int location, defcfg;
3216 int num_pins;
3217
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003218 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3219 /* use HP as primary out */
3220 cfg->speaker_outs = cfg->line_outs;
3221 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3222 sizeof(cfg->speaker_pins));
3223 cfg->line_outs = cfg->hp_outs;
3224 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3225 cfg->hp_outs = 0;
3226 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3227 cfg->line_out_type = AUTO_PIN_HP_OUT;
Takashi Iwaicb053a82011-06-27 11:32:07 +02003228 if (fill_dac)
3229 fill_dac(codec);
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003230 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003231 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003232 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003233 return 0;
3234
3235 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3236 location = get_defcfg_location(defcfg);
3237
3238 num_pins = alc_auto_fill_multi_ios(codec, location);
3239 if (num_pins > 0) {
3240 struct snd_kcontrol_new *knew;
3241
3242 knew = alc_kcontrol_new(spec);
3243 if (!knew)
3244 return -ENOMEM;
3245 *knew = alc_auto_channel_mode_enum;
3246 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3247 if (!knew->name)
3248 return -ENOMEM;
3249
3250 spec->multi_ios = num_pins;
3251 spec->ext_channel_count = 2;
3252 spec->multiout.num_dacs = num_pins + 1;
3253 }
3254 return 0;
3255}
3256
Takashi Iwai1d045db2011-07-07 18:23:21 +02003257/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3258 * active input pins
3259 */
3260static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3261{
3262 struct alc_spec *spec = codec->spec;
3263 const struct hda_input_mux *imux;
3264 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3265 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3266 int i, n, nums;
3267
3268 imux = spec->input_mux;
3269 if (!imux)
3270 return;
3271 if (spec->dyn_adc_switch)
3272 return;
3273
3274 nums = 0;
3275 for (n = 0; n < spec->num_adc_nids; n++) {
3276 hda_nid_t cap = spec->private_capsrc_nids[n];
3277 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3278 for (i = 0; i < imux->num_items; i++) {
3279 hda_nid_t pin = spec->imux_pins[i];
3280 if (pin) {
3281 if (get_connection_index(codec, cap, pin) < 0)
3282 break;
3283 } else if (num_conns <= imux->items[i].index)
3284 break;
3285 }
3286 if (i >= imux->num_items) {
3287 adc_nids[nums] = spec->private_adc_nids[n];
3288 capsrc_nids[nums++] = cap;
3289 }
3290 }
3291 if (!nums) {
3292 /* check whether ADC-switch is possible */
3293 if (!alc_check_dyn_adc_switch(codec)) {
3294 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3295 " using fallback 0x%x\n",
3296 codec->chip_name, spec->private_adc_nids[0]);
3297 spec->num_adc_nids = 1;
3298 spec->auto_mic = 0;
3299 return;
3300 }
3301 } else if (nums != spec->num_adc_nids) {
3302 memcpy(spec->private_adc_nids, adc_nids,
3303 nums * sizeof(hda_nid_t));
3304 memcpy(spec->private_capsrc_nids, capsrc_nids,
3305 nums * sizeof(hda_nid_t));
3306 spec->num_adc_nids = nums;
3307 }
3308
3309 if (spec->auto_mic)
3310 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3311 else if (spec->input_mux->num_items == 1)
3312 spec->num_adc_nids = 1; /* reduce to a single ADC */
3313}
3314
3315/*
3316 * initialize ADC paths
3317 */
3318static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3319{
3320 struct alc_spec *spec = codec->spec;
3321 hda_nid_t nid;
3322
3323 nid = spec->adc_nids[adc_idx];
3324 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003325 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003326 snd_hda_codec_write(codec, nid, 0,
3327 AC_VERB_SET_AMP_GAIN_MUTE,
3328 AMP_IN_MUTE(0));
3329 return;
3330 }
3331 if (!spec->capsrc_nids)
3332 return;
3333 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003334 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003335 snd_hda_codec_write(codec, nid, 0,
3336 AC_VERB_SET_AMP_GAIN_MUTE,
3337 AMP_OUT_MUTE);
3338}
3339
3340static void alc_auto_init_input_src(struct hda_codec *codec)
3341{
3342 struct alc_spec *spec = codec->spec;
3343 int c, nums;
3344
3345 for (c = 0; c < spec->num_adc_nids; c++)
3346 alc_auto_init_adc(codec, c);
3347 if (spec->dyn_adc_switch)
3348 nums = 1;
3349 else
3350 nums = spec->num_adc_nids;
3351 for (c = 0; c < nums; c++)
3352 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3353}
3354
3355/* add mic boosts if needed */
3356static int alc_auto_add_mic_boost(struct hda_codec *codec)
3357{
3358 struct alc_spec *spec = codec->spec;
3359 struct auto_pin_cfg *cfg = &spec->autocfg;
3360 int i, err;
3361 int type_idx = 0;
3362 hda_nid_t nid;
3363 const char *prev_label = NULL;
3364
3365 for (i = 0; i < cfg->num_inputs; i++) {
3366 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3367 break;
3368 nid = cfg->inputs[i].pin;
3369 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3370 const char *label;
3371 char boost_label[32];
3372
3373 label = hda_get_autocfg_input_label(codec, cfg, i);
3374 if (prev_label && !strcmp(label, prev_label))
3375 type_idx++;
3376 else
3377 type_idx = 0;
3378 prev_label = label;
3379
3380 snprintf(boost_label, sizeof(boost_label),
3381 "%s Boost Volume", label);
3382 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3383 boost_label, type_idx,
3384 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3385 if (err < 0)
3386 return err;
3387 }
3388 }
3389 return 0;
3390}
3391
3392/* select or unmute the given capsrc route */
3393static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3394 int idx)
3395{
3396 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3397 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3398 HDA_AMP_MUTE, 0);
3399 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3400 snd_hda_codec_write_cache(codec, cap, 0,
3401 AC_VERB_SET_CONNECT_SEL, idx);
3402 }
3403}
3404
3405/* set the default connection to that pin */
3406static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3407{
3408 struct alc_spec *spec = codec->spec;
3409 int i;
3410
3411 if (!pin)
3412 return 0;
3413 for (i = 0; i < spec->num_adc_nids; i++) {
3414 hda_nid_t cap = spec->capsrc_nids ?
3415 spec->capsrc_nids[i] : spec->adc_nids[i];
3416 int idx;
3417
3418 idx = get_connection_index(codec, cap, pin);
3419 if (idx < 0)
3420 continue;
3421 select_or_unmute_capsrc(codec, cap, idx);
3422 return i; /* return the found index */
3423 }
3424 return -1; /* not found */
3425}
3426
3427/* initialize some special cases for input sources */
3428static void alc_init_special_input_src(struct hda_codec *codec)
3429{
3430 struct alc_spec *spec = codec->spec;
3431 int i;
3432
3433 for (i = 0; i < spec->autocfg.num_inputs; i++)
3434 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3435}
3436
3437/* assign appropriate capture mixers */
3438static void set_capture_mixer(struct hda_codec *codec)
3439{
3440 struct alc_spec *spec = codec->spec;
3441 static const struct snd_kcontrol_new *caps[2][3] = {
3442 { alc_capture_mixer_nosrc1,
3443 alc_capture_mixer_nosrc2,
3444 alc_capture_mixer_nosrc3 },
3445 { alc_capture_mixer1,
3446 alc_capture_mixer2,
3447 alc_capture_mixer3 },
3448 };
3449
3450 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003451 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003452 if (!spec->capsrc_nids)
3453 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003454 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003455 return; /* no volume in capsrc, too */
3456 spec->vol_in_capsrc = 1;
3457 }
3458
3459 if (spec->num_adc_nids > 0) {
3460 int mux = 0;
3461 int num_adcs = 0;
3462
3463 if (spec->input_mux && spec->input_mux->num_items > 1)
3464 mux = 1;
3465 if (spec->auto_mic) {
3466 num_adcs = 1;
3467 mux = 0;
3468 } else if (spec->dyn_adc_switch)
3469 num_adcs = 1;
3470 if (!num_adcs) {
3471 if (spec->num_adc_nids > 3)
3472 spec->num_adc_nids = 3;
3473 else if (!spec->num_adc_nids)
3474 return;
3475 num_adcs = spec->num_adc_nids;
3476 }
3477 spec->cap_mixer = caps[mux][num_adcs - 1];
3478 }
3479}
3480
3481/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003482 * standard auto-parser initializations
3483 */
3484static void alc_auto_init_std(struct hda_codec *codec)
3485{
3486 struct alc_spec *spec = codec->spec;
3487 alc_auto_init_multi_out(codec);
3488 alc_auto_init_extra_out(codec);
3489 alc_auto_init_analog_input(codec);
3490 alc_auto_init_input_src(codec);
3491 alc_auto_init_digital(codec);
3492 if (spec->unsol_event)
3493 alc_inithook(codec);
3494}
3495
3496/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003497 * Digital-beep handlers
3498 */
3499#ifdef CONFIG_SND_HDA_INPUT_BEEP
3500#define set_beep_amp(spec, nid, idx, dir) \
3501 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3502
3503static const struct snd_pci_quirk beep_white_list[] = {
3504 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3505 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3506 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3507 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3508 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3509 {}
3510};
3511
3512static inline int has_cdefine_beep(struct hda_codec *codec)
3513{
3514 struct alc_spec *spec = codec->spec;
3515 const struct snd_pci_quirk *q;
3516 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3517 if (q)
3518 return q->value;
3519 return spec->cdefine.enable_pcbeep;
3520}
3521#else
3522#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3523#define has_cdefine_beep(codec) 0
3524#endif
3525
3526/* parse the BIOS configuration and set up the alc_spec */
3527/* return 1 if successful, 0 if the proper config is not found,
3528 * or a negative error code
3529 */
3530static int alc880_parse_auto_config(struct hda_codec *codec)
3531{
3532 struct alc_spec *spec = codec->spec;
3533 int err;
3534 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3535
3536 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3537 alc880_ignore);
3538 if (err < 0)
3539 return err;
3540 if (!spec->autocfg.line_outs)
3541 return 0; /* can't find valid BIOS pin config */
3542
3543 err = alc_auto_fill_dac_nids(codec);
3544 if (err < 0)
3545 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003546 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
3547 if (err < 0)
3548 return err;
3549 err = alc_auto_create_hp_out(codec);
3550 if (err < 0)
3551 return err;
3552 err = alc_auto_create_speaker_out(codec);
3553 if (err < 0)
3554 return err;
3555 err = alc_auto_create_input_ctls(codec);
3556 if (err < 0)
3557 return err;
3558
3559 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3560
3561 alc_auto_parse_digital(codec);
3562
3563 if (spec->kctls.list)
3564 add_mixer(spec, spec->kctls.list);
3565
3566 alc_remove_invalid_adc_nids(codec);
3567
3568 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
3569 alc_auto_check_switches(codec);
3570
3571 return 1;
3572}
3573
Takashi Iwai1d045db2011-07-07 18:23:21 +02003574#ifdef CONFIG_SND_HDA_POWER_SAVE
3575static const struct hda_amp_list alc880_loopbacks[] = {
3576 { 0x0b, HDA_INPUT, 0 },
3577 { 0x0b, HDA_INPUT, 1 },
3578 { 0x0b, HDA_INPUT, 2 },
3579 { 0x0b, HDA_INPUT, 3 },
3580 { 0x0b, HDA_INPUT, 4 },
3581 { } /* end */
3582};
3583#endif
3584
3585/*
3586 * board setups
3587 */
3588#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3589#define alc_board_config \
3590 snd_hda_check_board_config
3591#define alc_board_codec_sid_config \
3592 snd_hda_check_board_codec_sid_config
3593#include "alc_quirks.c"
3594#else
3595#define alc_board_config(codec, nums, models, tbl) -1
3596#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3597#define setup_preset(codec, x) /* NOP */
3598#endif
3599
3600/*
3601 * OK, here we have finally the patch for ALC880
3602 */
3603#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3604#include "alc880_quirks.c"
3605#endif
3606
3607static int patch_alc880(struct hda_codec *codec)
3608{
3609 struct alc_spec *spec;
3610 int board_config;
3611 int err;
3612
3613 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3614 if (spec == NULL)
3615 return -ENOMEM;
3616
3617 codec->spec = spec;
3618
3619 spec->mixer_nid = 0x0b;
3620
3621 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3622 alc880_models, alc880_cfg_tbl);
3623 if (board_config < 0) {
3624 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3625 codec->chip_name);
3626 board_config = ALC_MODEL_AUTO;
3627 }
3628
3629 if (board_config == ALC_MODEL_AUTO) {
3630 /* automatic parse from the BIOS config */
3631 err = alc880_parse_auto_config(codec);
3632 if (err < 0) {
3633 alc_free(codec);
3634 return err;
3635 }
3636#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3637 else if (!err) {
3638 printk(KERN_INFO
3639 "hda_codec: Cannot set up configuration "
3640 "from BIOS. Using 3-stack mode...\n");
3641 board_config = ALC880_3ST;
3642 }
3643#endif
3644 }
3645
3646 err = snd_hda_attach_beep_device(codec, 0x1);
3647 if (err < 0) {
3648 alc_free(codec);
3649 return err;
3650 }
3651
3652 if (board_config != ALC_MODEL_AUTO)
3653 setup_preset(codec, &alc880_presets[board_config]);
3654
3655 if (!spec->adc_nids && spec->input_mux) {
3656 alc_auto_fill_adc_caps(codec);
3657 alc_rebuild_imux_for_auto_mic(codec);
3658 alc_remove_invalid_adc_nids(codec);
3659 }
3660 set_capture_mixer(codec);
3661 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3662
3663 spec->vmaster_nid = 0x0c;
3664
3665 codec->patch_ops = alc_patch_ops;
3666 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003667 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003668#ifdef CONFIG_SND_HDA_POWER_SAVE
3669 if (!spec->loopback.amplist)
3670 spec->loopback.amplist = alc880_loopbacks;
3671#endif
3672
3673 return 0;
3674}
3675
3676
3677/*
3678 * ALC260 support
3679 */
3680
3681/* convert from pin to volume-mixer widget */
3682static hda_nid_t alc260_pin_to_vol_mix(hda_nid_t nid)
3683{
3684 if (nid >= 0x0f && nid <= 0x11)
3685 return nid - 0x7;
3686 else if (nid >= 0x12 && nid <= 0x15)
3687 return 0x08;
3688 else
3689 return 0;
3690}
3691
3692static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
3693 const char *pfx, int *vol_bits)
3694{
3695 hda_nid_t nid_vol;
3696 unsigned long vol_val, sw_val;
3697 int chs, err;
3698
3699 nid_vol = alc260_pin_to_vol_mix(nid);
3700 if (!nid_vol)
3701 return 0; /* N/A */
3702 if (nid == 0x11)
3703 chs = 2;
3704 else
3705 chs = 3;
3706 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, chs, 0, HDA_OUTPUT);
3707 sw_val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
3708
3709 if (!(*vol_bits & (1 << nid_vol))) {
3710 /* first control for the volume widget */
3711 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
3712 if (err < 0)
3713 return err;
3714 *vol_bits |= (1 << nid_vol);
3715 }
3716 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
3717 if (err < 0)
3718 return err;
3719 return 1;
3720}
3721
3722/* add playback controls from the parsed DAC table */
3723static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
3724 const struct auto_pin_cfg *cfg)
3725{
3726 hda_nid_t nid;
3727 int err;
3728 int vols = 0;
3729
3730 spec->multiout.num_dacs = 1;
3731 spec->multiout.dac_nids = spec->private_dac_nids;
3732 spec->private_dac_nids[0] = 0x02;
3733
3734 nid = cfg->line_out_pins[0];
3735 if (nid) {
3736 const char *pfx;
3737 int index;
3738 pfx = alc_get_line_out_pfx(spec, 0, true, &index);
3739 err = alc260_add_playback_controls(spec, nid, pfx, &vols);
3740 if (err < 0)
3741 return err;
3742 }
3743
3744 nid = cfg->speaker_pins[0];
3745 if (nid) {
3746 err = alc260_add_playback_controls(spec, nid, "Speaker", &vols);
3747 if (err < 0)
3748 return err;
3749 }
3750
3751 nid = cfg->hp_pins[0];
3752 if (nid) {
3753 err = alc260_add_playback_controls(spec, nid, "Headphone",
3754 &vols);
3755 if (err < 0)
3756 return err;
3757 }
3758 return 0;
3759}
3760
3761static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
3762 hda_nid_t nid, int pin_type,
3763 int sel_idx)
3764{
3765 hda_nid_t mix;
3766
3767 alc_set_pin_output(codec, nid, pin_type);
3768 /* need the manual connection? */
3769 if (nid >= 0x12) {
3770 int idx = nid - 0x12;
3771 snd_hda_codec_write(codec, idx + 0x0b, 0,
3772 AC_VERB_SET_CONNECT_SEL, sel_idx);
3773 }
3774
3775 mix = alc260_pin_to_vol_mix(nid);
3776 if (!mix)
3777 return;
3778 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3779 AMP_OUT_ZERO);
3780 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3781 AMP_IN_UNMUTE(0));
3782 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3783 AMP_IN_UNMUTE(1));
3784}
3785
3786static void alc260_auto_init_multi_out(struct hda_codec *codec)
3787{
3788 struct alc_spec *spec = codec->spec;
3789 hda_nid_t nid;
3790
3791 nid = spec->autocfg.line_out_pins[0];
3792 if (nid) {
3793 int pin_type = get_pin_type(spec->autocfg.line_out_type);
3794 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
3795 }
3796
3797 nid = spec->autocfg.speaker_pins[0];
3798 if (nid)
3799 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3800
3801 nid = spec->autocfg.hp_pins[0];
3802 if (nid)
3803 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
3804}
3805
3806static int alc260_parse_auto_config(struct hda_codec *codec)
3807{
3808 struct alc_spec *spec = codec->spec;
3809 int err;
3810 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
3811
3812 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3813 alc260_ignore);
3814 if (err < 0)
3815 return err;
3816 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
3817 if (err < 0)
3818 return err;
3819 if (!spec->kctls.list)
3820 return 0; /* can't find valid BIOS pin config */
3821 err = alc_auto_create_input_ctls(codec);
3822 if (err < 0)
3823 return err;
3824
3825 spec->multiout.max_channels = 2;
3826
3827 alc_auto_parse_digital(codec);
3828
3829 if (spec->kctls.list)
3830 add_mixer(spec, spec->kctls.list);
3831
3832 alc_remove_invalid_adc_nids(codec);
3833
3834 alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
3835 alc_auto_check_switches(codec);
3836
3837 return 1;
3838}
3839
3840/* additional initialization for auto-configuration model */
3841static void alc260_auto_init(struct hda_codec *codec)
3842{
3843 struct alc_spec *spec = codec->spec;
3844 alc260_auto_init_multi_out(codec);
3845 alc_auto_init_analog_input(codec);
3846 alc_auto_init_input_src(codec);
3847 alc_auto_init_digital(codec);
3848 if (spec->unsol_event)
3849 alc_inithook(codec);
3850}
3851
3852#ifdef CONFIG_SND_HDA_POWER_SAVE
3853static const struct hda_amp_list alc260_loopbacks[] = {
3854 { 0x07, HDA_INPUT, 0 },
3855 { 0x07, HDA_INPUT, 1 },
3856 { 0x07, HDA_INPUT, 2 },
3857 { 0x07, HDA_INPUT, 3 },
3858 { 0x07, HDA_INPUT, 4 },
3859 { } /* end */
3860};
3861#endif
3862
3863/*
3864 * Pin config fixes
3865 */
3866enum {
3867 PINFIX_HP_DC5750,
3868};
3869
3870static const struct alc_fixup alc260_fixups[] = {
3871 [PINFIX_HP_DC5750] = {
3872 .type = ALC_FIXUP_PINS,
3873 .v.pins = (const struct alc_pincfg[]) {
3874 { 0x11, 0x90130110 }, /* speaker */
3875 { }
3876 }
3877 },
3878};
3879
3880static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3881 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3882 {}
3883};
3884
3885/*
3886 */
3887#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3888#include "alc260_quirks.c"
3889#endif
3890
3891static int patch_alc260(struct hda_codec *codec)
3892{
3893 struct alc_spec *spec;
3894 int err, board_config;
3895
3896 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3897 if (spec == NULL)
3898 return -ENOMEM;
3899
3900 codec->spec = spec;
3901
3902 spec->mixer_nid = 0x07;
3903
3904 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3905 alc260_models, alc260_cfg_tbl);
3906 if (board_config < 0) {
3907 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3908 codec->chip_name);
3909 board_config = ALC_MODEL_AUTO;
3910 }
3911
3912 if (board_config == ALC_MODEL_AUTO) {
3913 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3914 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3915 }
3916
3917 if (board_config == ALC_MODEL_AUTO) {
3918 /* automatic parse from the BIOS config */
3919 err = alc260_parse_auto_config(codec);
3920 if (err < 0) {
3921 alc_free(codec);
3922 return err;
3923 }
3924#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3925 else if (!err) {
3926 printk(KERN_INFO
3927 "hda_codec: Cannot set up configuration "
3928 "from BIOS. Using base mode...\n");
3929 board_config = ALC260_BASIC;
3930 }
3931#endif
3932 }
3933
3934 err = snd_hda_attach_beep_device(codec, 0x1);
3935 if (err < 0) {
3936 alc_free(codec);
3937 return err;
3938 }
3939
3940 if (board_config != ALC_MODEL_AUTO)
3941 setup_preset(codec, &alc260_presets[board_config]);
3942
3943 if (!spec->adc_nids && spec->input_mux) {
3944 alc_auto_fill_adc_caps(codec);
3945 alc_rebuild_imux_for_auto_mic(codec);
3946 alc_remove_invalid_adc_nids(codec);
3947 }
3948 set_capture_mixer(codec);
3949 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3950
3951 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3952
3953 spec->vmaster_nid = 0x08;
3954
3955 codec->patch_ops = alc_patch_ops;
3956 if (board_config == ALC_MODEL_AUTO)
3957 spec->init_hook = alc260_auto_init;
3958 spec->shutup = alc_eapd_shutup;
3959#ifdef CONFIG_SND_HDA_POWER_SAVE
3960 if (!spec->loopback.amplist)
3961 spec->loopback.amplist = alc260_loopbacks;
3962#endif
3963
3964 return 0;
3965}
3966
3967
3968/*
3969 * ALC882/883/885/888/889 support
3970 *
3971 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3972 * configuration. Each pin widget can choose any input DACs and a mixer.
3973 * Each ADC is connected from a mixer of all inputs. This makes possible
3974 * 6-channel independent captures.
3975 *
3976 * In addition, an independent DAC for the multi-playback (not used in this
3977 * driver yet).
3978 */
3979#ifdef CONFIG_SND_HDA_POWER_SAVE
3980#define alc882_loopbacks alc880_loopbacks
3981#endif
3982
3983/*
3984 * Pin config fixes
3985 */
3986enum {
3987 PINFIX_ABIT_AW9D_MAX,
3988 PINFIX_LENOVO_Y530,
3989 PINFIX_PB_M5210,
3990 PINFIX_ACER_ASPIRE_7736,
3991};
3992
3993static const struct alc_fixup alc882_fixups[] = {
3994 [PINFIX_ABIT_AW9D_MAX] = {
3995 .type = ALC_FIXUP_PINS,
3996 .v.pins = (const struct alc_pincfg[]) {
3997 { 0x15, 0x01080104 }, /* side */
3998 { 0x16, 0x01011012 }, /* rear */
3999 { 0x17, 0x01016011 }, /* clfe */
4000 { }
4001 }
4002 },
4003 [PINFIX_LENOVO_Y530] = {
4004 .type = ALC_FIXUP_PINS,
4005 .v.pins = (const struct alc_pincfg[]) {
4006 { 0x15, 0x99130112 }, /* rear int speakers */
4007 { 0x16, 0x99130111 }, /* subwoofer */
4008 { }
4009 }
4010 },
4011 [PINFIX_PB_M5210] = {
4012 .type = ALC_FIXUP_VERBS,
4013 .v.verbs = (const struct hda_verb[]) {
4014 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
4015 {}
4016 }
4017 },
4018 [PINFIX_ACER_ASPIRE_7736] = {
4019 .type = ALC_FIXUP_SKU,
4020 .v.sku = ALC_FIXUP_SKU_IGNORE,
4021 },
4022};
4023
4024static const struct snd_pci_quirk alc882_fixup_tbl[] = {
4025 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
4026 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
4027 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
4028 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
4029 {}
4030};
4031
4032/*
4033 * BIOS auto configuration
4034 */
4035/* almost identical with ALC880 parser... */
4036static int alc882_parse_auto_config(struct hda_codec *codec)
4037{
4038 struct alc_spec *spec = codec->spec;
4039 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
4040 int err;
4041
4042 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4043 alc882_ignore);
4044 if (err < 0)
4045 return err;
4046 if (!spec->autocfg.line_outs)
4047 return 0; /* can't find valid BIOS pin config */
4048
4049 err = alc_auto_fill_dac_nids(codec);
4050 if (err < 0)
4051 return err;
4052 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
4053 if (err < 0)
4054 return err;
4055 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
4056 if (err < 0)
4057 return err;
4058 err = alc_auto_create_hp_out(codec);
4059 if (err < 0)
4060 return err;
4061 err = alc_auto_create_speaker_out(codec);
4062 if (err < 0)
4063 return err;
4064 err = alc_auto_create_input_ctls(codec);
4065 if (err < 0)
4066 return err;
4067
4068 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4069
4070 alc_auto_parse_digital(codec);
4071
4072 if (spec->kctls.list)
4073 add_mixer(spec, spec->kctls.list);
4074
4075 err = alc_auto_add_mic_boost(codec);
4076 if (err < 0)
4077 return err;
4078
4079 alc_remove_invalid_adc_nids(codec);
4080
4081 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
4082 alc_auto_check_switches(codec);
4083
4084 return 1; /* config found */
4085}
4086
Takashi Iwai1d045db2011-07-07 18:23:21 +02004087/*
4088 */
4089#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4090#include "alc882_quirks.c"
4091#endif
4092
4093static int patch_alc882(struct hda_codec *codec)
4094{
4095 struct alc_spec *spec;
4096 int err, board_config;
4097
4098 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4099 if (spec == NULL)
4100 return -ENOMEM;
4101
4102 codec->spec = spec;
4103
4104 spec->mixer_nid = 0x0b;
4105
4106 switch (codec->vendor_id) {
4107 case 0x10ec0882:
4108 case 0x10ec0885:
4109 break;
4110 default:
4111 /* ALC883 and variants */
4112 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4113 break;
4114 }
4115
4116 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
4117 alc882_models, alc882_cfg_tbl);
4118
4119 if (board_config < 0)
4120 board_config = alc_board_codec_sid_config(codec,
4121 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
4122
4123 if (board_config < 0) {
4124 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4125 codec->chip_name);
4126 board_config = ALC_MODEL_AUTO;
4127 }
4128
4129 if (board_config == ALC_MODEL_AUTO) {
4130 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
4131 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4132 }
4133
4134 alc_auto_parse_customize_define(codec);
4135
4136 if (board_config == ALC_MODEL_AUTO) {
4137 /* automatic parse from the BIOS config */
4138 err = alc882_parse_auto_config(codec);
4139 if (err < 0) {
4140 alc_free(codec);
4141 return err;
4142 }
4143#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4144 else if (!err) {
4145 printk(KERN_INFO
4146 "hda_codec: Cannot set up configuration "
4147 "from BIOS. Using base mode...\n");
4148 board_config = ALC882_3ST_DIG;
4149 }
4150#endif
4151 }
4152
4153 if (has_cdefine_beep(codec)) {
4154 err = snd_hda_attach_beep_device(codec, 0x1);
4155 if (err < 0) {
4156 alc_free(codec);
4157 return err;
4158 }
4159 }
4160
4161 if (board_config != ALC_MODEL_AUTO)
4162 setup_preset(codec, &alc882_presets[board_config]);
4163
4164 if (!spec->adc_nids && spec->input_mux) {
4165 alc_auto_fill_adc_caps(codec);
4166 alc_rebuild_imux_for_auto_mic(codec);
4167 alc_remove_invalid_adc_nids(codec);
4168 }
4169
4170 set_capture_mixer(codec);
4171
4172 if (has_cdefine_beep(codec))
4173 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
4174
4175 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4176
4177 spec->vmaster_nid = 0x0c;
4178
4179 codec->patch_ops = alc_patch_ops;
4180 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004181 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004182
4183 alc_init_jacks(codec);
4184#ifdef CONFIG_SND_HDA_POWER_SAVE
4185 if (!spec->loopback.amplist)
4186 spec->loopback.amplist = alc882_loopbacks;
4187#endif
4188
4189 return 0;
4190}
4191
4192
4193/*
4194 * ALC262 support
4195 */
4196
4197/* We use two mixers depending on the output pin; 0x16 is a mono output
4198 * and thus it's bound with a different mixer.
4199 * This function returns which mixer amp should be used.
4200 */
4201static int alc262_check_volbit(hda_nid_t nid)
4202{
4203 if (!nid)
4204 return 0;
4205 else if (nid == 0x16)
4206 return 2;
4207 else
4208 return 1;
4209}
4210
4211static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
4212 const char *pfx, int *vbits, int idx)
4213{
4214 unsigned long val;
4215 int vbit;
4216
4217 vbit = alc262_check_volbit(nid);
4218 if (!vbit)
4219 return 0;
4220 if (*vbits & vbit) /* a volume control for this mixer already there */
4221 return 0;
4222 *vbits |= vbit;
4223 if (vbit == 2)
4224 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
4225 else
4226 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
4227 return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val);
4228}
4229
4230static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
4231 const char *pfx, int idx)
4232{
4233 unsigned long val;
4234
4235 if (!nid)
4236 return 0;
4237 if (nid == 0x16)
4238 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
4239 else
4240 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
4241 return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val);
4242}
4243
4244/* add playback controls from the parsed DAC table */
4245static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
4246 const struct auto_pin_cfg *cfg)
4247{
4248 const char *pfx;
4249 int vbits;
4250 int i, index, err;
4251
4252 spec->multiout.num_dacs = 1; /* only use one dac */
4253 spec->multiout.dac_nids = spec->private_dac_nids;
4254 spec->private_dac_nids[0] = 2;
4255
4256 for (i = 0; i < 2; i++) {
4257 pfx = alc_get_line_out_pfx(spec, i, true, &index);
4258 if (!pfx)
4259 pfx = "PCM";
4260 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx,
4261 index);
4262 if (err < 0)
4263 return err;
4264 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4265 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i],
4266 "Speaker", i);
4267 if (err < 0)
4268 return err;
4269 }
4270 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4271 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i],
4272 "Headphone", i);
4273 if (err < 0)
4274 return err;
4275 }
4276 }
4277
4278 vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
4279 alc262_check_volbit(cfg->speaker_pins[0]) |
4280 alc262_check_volbit(cfg->hp_pins[0]);
4281 vbits = 0;
4282 for (i = 0; i < 2; i++) {
4283 pfx = alc_get_line_out_pfx(spec, i, true, &index);
4284 if (!pfx)
4285 pfx = "PCM";
4286 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx,
4287 &vbits, i);
4288 if (err < 0)
4289 return err;
4290 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4291 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i],
4292 "Speaker", &vbits, i);
4293 if (err < 0)
4294 return err;
4295 }
4296 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4297 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i],
4298 "Headphone", &vbits, i);
4299 if (err < 0)
4300 return err;
4301 }
4302 }
4303 return 0;
4304}
4305
4306/*
4307 * BIOS auto configuration
4308 */
4309static int alc262_parse_auto_config(struct hda_codec *codec)
4310{
4311 struct alc_spec *spec = codec->spec;
4312 int err;
4313 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
4314
4315 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4316 alc262_ignore);
4317 if (err < 0)
4318 return err;
4319 if (!spec->autocfg.line_outs) {
4320 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
4321 spec->multiout.max_channels = 2;
4322 spec->no_analog = 1;
4323 goto dig_only;
4324 }
4325 return 0; /* can't find valid BIOS pin config */
4326 }
4327 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
4328 if (err < 0)
4329 return err;
4330 err = alc_auto_create_input_ctls(codec);
4331 if (err < 0)
4332 return err;
4333
4334 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4335
4336 dig_only:
4337 alc_auto_parse_digital(codec);
4338
4339 if (spec->kctls.list)
4340 add_mixer(spec, spec->kctls.list);
4341
4342 err = alc_auto_add_mic_boost(codec);
4343 if (err < 0)
4344 return err;
4345
4346 alc_remove_invalid_adc_nids(codec);
4347
4348 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
4349 alc_auto_check_switches(codec);
4350
4351 return 1;
4352}
4353
4354/*
4355 * Pin config fixes
4356 */
4357enum {
4358 PINFIX_FSC_H270,
4359 PINFIX_HP_Z200,
4360};
4361
4362static const struct alc_fixup alc262_fixups[] = {
4363 [PINFIX_FSC_H270] = {
4364 .type = ALC_FIXUP_PINS,
4365 .v.pins = (const struct alc_pincfg[]) {
4366 { 0x14, 0x99130110 }, /* speaker */
4367 { 0x15, 0x0221142f }, /* front HP */
4368 { 0x1b, 0x0121141f }, /* rear HP */
4369 { }
4370 }
4371 },
4372 [PINFIX_HP_Z200] = {
4373 .type = ALC_FIXUP_PINS,
4374 .v.pins = (const struct alc_pincfg[]) {
4375 { 0x16, 0x99130120 }, /* internal speaker */
4376 { }
4377 }
4378 },
4379};
4380
4381static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4382 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4383 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4384 {}
4385};
4386
4387
4388#ifdef CONFIG_SND_HDA_POWER_SAVE
4389#define alc262_loopbacks alc880_loopbacks
4390#endif
4391
Takashi Iwai1d045db2011-07-07 18:23:21 +02004392/*
4393 */
4394#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4395#include "alc262_quirks.c"
4396#endif
4397
4398static int patch_alc262(struct hda_codec *codec)
4399{
4400 struct alc_spec *spec;
4401 int board_config;
4402 int err;
4403
4404 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4405 if (spec == NULL)
4406 return -ENOMEM;
4407
4408 codec->spec = spec;
4409
4410 spec->mixer_nid = 0x0b;
4411
4412#if 0
4413 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4414 * under-run
4415 */
4416 {
4417 int tmp;
4418 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4419 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4420 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4421 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4422 }
4423#endif
4424 alc_auto_parse_customize_define(codec);
4425
4426 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4427
4428 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4429 alc262_models, alc262_cfg_tbl);
4430
4431 if (board_config < 0) {
4432 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4433 codec->chip_name);
4434 board_config = ALC_MODEL_AUTO;
4435 }
4436
4437 if (board_config == ALC_MODEL_AUTO) {
4438 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4439 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4440 }
4441
4442 if (board_config == ALC_MODEL_AUTO) {
4443 /* automatic parse from the BIOS config */
4444 err = alc262_parse_auto_config(codec);
4445 if (err < 0) {
4446 alc_free(codec);
4447 return err;
4448 }
4449#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4450 else if (!err) {
4451 printk(KERN_INFO
4452 "hda_codec: Cannot set up configuration "
4453 "from BIOS. Using base mode...\n");
4454 board_config = ALC262_BASIC;
4455 }
4456#endif
4457 }
4458
4459 if (!spec->no_analog && has_cdefine_beep(codec)) {
4460 err = snd_hda_attach_beep_device(codec, 0x1);
4461 if (err < 0) {
4462 alc_free(codec);
4463 return err;
4464 }
4465 }
4466
4467 if (board_config != ALC_MODEL_AUTO)
4468 setup_preset(codec, &alc262_presets[board_config]);
4469
4470 if (!spec->adc_nids && spec->input_mux) {
4471 alc_auto_fill_adc_caps(codec);
4472 alc_rebuild_imux_for_auto_mic(codec);
4473 alc_remove_invalid_adc_nids(codec);
4474 }
4475 if (!spec->cap_mixer && !spec->no_analog)
4476 set_capture_mixer(codec);
4477 if (!spec->no_analog && has_cdefine_beep(codec))
4478 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
4479
4480 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4481
4482 spec->vmaster_nid = 0x0c;
4483
4484 codec->patch_ops = alc_patch_ops;
4485 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004486 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004487 spec->shutup = alc_eapd_shutup;
4488
4489 alc_init_jacks(codec);
4490#ifdef CONFIG_SND_HDA_POWER_SAVE
4491 if (!spec->loopback.amplist)
4492 spec->loopback.amplist = alc262_loopbacks;
4493#endif
4494
4495 return 0;
4496}
4497
4498/*
4499 * ALC268
4500 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004501/* bind Beep switches of both NID 0x0f and 0x10 */
4502static const struct hda_bind_ctls alc268_bind_beep_sw = {
4503 .ops = &snd_hda_bind_sw,
4504 .values = {
4505 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4506 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4507 0
4508 },
4509};
4510
4511static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4512 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4513 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4514 { }
4515};
4516
4517/* set PCBEEP vol = 0, mute connections */
4518static const struct hda_verb alc268_beep_init_verbs[] = {
4519 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4520 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4521 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4522 { }
4523};
4524
4525/*
4526 * BIOS auto configuration
4527 */
4528static int alc268_parse_auto_config(struct hda_codec *codec)
4529{
4530 struct alc_spec *spec = codec->spec;
4531 int err;
4532 static const hda_nid_t alc268_ignore[] = { 0 };
4533
4534 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4535 alc268_ignore);
4536 if (err < 0)
4537 return err;
4538 if (!spec->autocfg.line_outs) {
4539 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
4540 spec->multiout.max_channels = 2;
4541 spec->no_analog = 1;
4542 goto dig_only;
4543 }
4544 return 0; /* can't find valid BIOS pin config */
4545 }
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004546
4547 err = alc_auto_fill_dac_nids(codec);
4548 if (err < 0)
4549 return err;
4550 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
4551 if (err < 0)
4552 return err;
4553 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
4554 if (err < 0)
4555 return err;
4556 err = alc_auto_create_hp_out(codec);
4557 if (err < 0)
4558 return err;
4559 err = alc_auto_create_speaker_out(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004560 if (err < 0)
4561 return err;
4562 err = alc_auto_create_input_ctls(codec);
4563 if (err < 0)
4564 return err;
4565
4566 spec->multiout.max_channels = 2;
4567
4568 dig_only:
4569 /* digital only support output */
4570 alc_auto_parse_digital(codec);
4571 if (spec->kctls.list)
4572 add_mixer(spec, spec->kctls.list);
4573
4574 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4575 add_mixer(spec, alc268_beep_mixer);
4576 add_verb(spec, alc268_beep_init_verbs);
4577 }
4578
4579 err = alc_auto_add_mic_boost(codec);
4580 if (err < 0)
4581 return err;
4582
4583 alc_remove_invalid_adc_nids(codec);
4584
4585 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
4586 alc_auto_check_switches(codec);
4587
4588 return 1;
4589}
4590
Takashi Iwai1d045db2011-07-07 18:23:21 +02004591/*
4592 */
4593#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4594#include "alc268_quirks.c"
4595#endif
4596
4597static int patch_alc268(struct hda_codec *codec)
4598{
4599 struct alc_spec *spec;
4600 int board_config;
4601 int i, has_beep, err;
4602
4603 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4604 if (spec == NULL)
4605 return -ENOMEM;
4606
4607 codec->spec = spec;
4608
4609 /* ALC268 has no aa-loopback mixer */
4610
4611 board_config = alc_board_config(codec, ALC268_MODEL_LAST,
4612 alc268_models, alc268_cfg_tbl);
4613
4614 if (board_config < 0)
4615 board_config = alc_board_codec_sid_config(codec,
4616 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
4617
4618 if (board_config < 0) {
4619 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4620 codec->chip_name);
4621 board_config = ALC_MODEL_AUTO;
4622 }
4623
4624 if (board_config == ALC_MODEL_AUTO) {
4625 /* automatic parse from the BIOS config */
4626 err = alc268_parse_auto_config(codec);
4627 if (err < 0) {
4628 alc_free(codec);
4629 return err;
4630 }
4631#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4632 else if (!err) {
4633 printk(KERN_INFO
4634 "hda_codec: Cannot set up configuration "
4635 "from BIOS. Using base mode...\n");
4636 board_config = ALC268_3ST;
4637 }
4638#endif
4639 }
4640
4641 if (board_config != ALC_MODEL_AUTO)
4642 setup_preset(codec, &alc268_presets[board_config]);
4643
4644 has_beep = 0;
4645 for (i = 0; i < spec->num_mixers; i++) {
4646 if (spec->mixers[i] == alc268_beep_mixer) {
4647 has_beep = 1;
4648 break;
4649 }
4650 }
4651
4652 if (has_beep) {
4653 err = snd_hda_attach_beep_device(codec, 0x1);
4654 if (err < 0) {
4655 alc_free(codec);
4656 return err;
4657 }
4658 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4659 /* override the amp caps for beep generator */
4660 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4661 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4662 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4663 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4664 (0 << AC_AMPCAP_MUTE_SHIFT));
4665 }
4666
4667 if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
4668 alc_auto_fill_adc_caps(codec);
4669 alc_rebuild_imux_for_auto_mic(codec);
4670 alc_remove_invalid_adc_nids(codec);
4671 }
4672
4673 if (!spec->cap_mixer && !spec->no_analog)
4674 set_capture_mixer(codec);
4675
4676 spec->vmaster_nid = 0x02;
4677
4678 codec->patch_ops = alc_patch_ops;
4679 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004680 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004681 spec->shutup = alc_eapd_shutup;
4682
4683 alc_init_jacks(codec);
4684
4685 return 0;
4686}
4687
4688/*
4689 * ALC269
4690 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004691#ifdef CONFIG_SND_HDA_POWER_SAVE
4692#define alc269_loopbacks alc880_loopbacks
4693#endif
4694
4695static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4696 .substreams = 1,
4697 .channels_min = 2,
4698 .channels_max = 8,
4699 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4700 /* NID is set in alc_build_pcms */
4701 .ops = {
4702 .open = alc_playback_pcm_open,
4703 .prepare = alc_playback_pcm_prepare,
4704 .cleanup = alc_playback_pcm_cleanup
4705 },
4706};
4707
4708static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4709 .substreams = 1,
4710 .channels_min = 2,
4711 .channels_max = 2,
4712 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4713 /* NID is set in alc_build_pcms */
4714};
4715
4716#ifdef CONFIG_SND_HDA_POWER_SAVE
4717static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4718{
4719 switch (codec->subsystem_id) {
4720 case 0x103c1586:
4721 return 1;
4722 }
4723 return 0;
4724}
4725
4726static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4727{
4728 /* update mute-LED according to the speaker mute state */
4729 if (nid == 0x01 || nid == 0x14) {
4730 int pinval;
4731 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4732 HDA_AMP_MUTE)
4733 pinval = 0x24;
4734 else
4735 pinval = 0x20;
4736 /* mic2 vref pin is used for mute LED control */
4737 snd_hda_codec_update_cache(codec, 0x19, 0,
4738 AC_VERB_SET_PIN_WIDGET_CONTROL,
4739 pinval);
4740 }
4741 return alc_check_power_status(codec, nid);
4742}
4743#endif /* CONFIG_SND_HDA_POWER_SAVE */
4744
4745/* different alc269-variants */
4746enum {
4747 ALC269_TYPE_ALC269VA,
4748 ALC269_TYPE_ALC269VB,
4749 ALC269_TYPE_ALC269VC,
4750};
4751
4752/*
4753 * BIOS auto configuration
4754 */
4755static int alc269_parse_auto_config(struct hda_codec *codec)
4756{
4757 struct alc_spec *spec = codec->spec;
4758 int err;
4759 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
4760
4761 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4762 alc269_ignore);
4763 if (err < 0)
4764 return err;
4765
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004766 err = alc_auto_fill_dac_nids(codec);
4767 if (err < 0)
4768 return err;
4769 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
4770 if (err < 0)
4771 return err;
4772 err = alc_auto_create_hp_out(codec);
4773 if (err < 0)
4774 return err;
4775 err = alc_auto_create_speaker_out(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004776 if (err < 0)
4777 return err;
4778 err = alc_auto_create_input_ctls(codec);
4779 if (err < 0)
4780 return err;
4781
4782 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4783
4784 alc_auto_parse_digital(codec);
4785
4786 if (spec->kctls.list)
4787 add_mixer(spec, spec->kctls.list);
4788
4789 alc_remove_invalid_adc_nids(codec);
4790
4791 if (spec->codec_variant != ALC269_TYPE_ALC269VA)
4792 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
4793 else
4794 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
4795 alc_auto_check_switches(codec);
4796
4797 err = alc_auto_add_mic_boost(codec);
4798 if (err < 0)
4799 return err;
4800
4801 if (!spec->cap_mixer && !spec->no_analog)
4802 set_capture_mixer(codec);
4803
4804 return 1;
4805}
4806
Takashi Iwai1d045db2011-07-07 18:23:21 +02004807static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4808{
4809 int val = alc_read_coef_idx(codec, 0x04);
4810 if (power_up)
4811 val |= 1 << 11;
4812 else
4813 val &= ~(1 << 11);
4814 alc_write_coef_idx(codec, 0x04, val);
4815}
4816
4817static void alc269_shutup(struct hda_codec *codec)
4818{
4819 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4820 alc269_toggle_power_output(codec, 0);
4821 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4822 alc269_toggle_power_output(codec, 0);
4823 msleep(150);
4824 }
4825}
4826
4827#ifdef SND_HDA_NEEDS_RESUME
4828static int alc269_resume(struct hda_codec *codec)
4829{
4830 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4831 alc269_toggle_power_output(codec, 0);
4832 msleep(150);
4833 }
4834
4835 codec->patch_ops.init(codec);
4836
4837 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4838 alc269_toggle_power_output(codec, 1);
4839 msleep(200);
4840 }
4841
4842 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4843 alc269_toggle_power_output(codec, 1);
4844
4845 snd_hda_codec_resume_amp(codec);
4846 snd_hda_codec_resume_cache(codec);
4847 hda_call_check_power_status(codec, 0x01);
4848 return 0;
4849}
4850#endif /* SND_HDA_NEEDS_RESUME */
4851
4852static void alc269_fixup_hweq(struct hda_codec *codec,
4853 const struct alc_fixup *fix, int action)
4854{
4855 int coef;
4856
4857 if (action != ALC_FIXUP_ACT_INIT)
4858 return;
4859 coef = alc_read_coef_idx(codec, 0x1e);
4860 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4861}
4862
4863static void alc271_fixup_dmic(struct hda_codec *codec,
4864 const struct alc_fixup *fix, int action)
4865{
4866 static const struct hda_verb verbs[] = {
4867 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4868 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4869 {}
4870 };
4871 unsigned int cfg;
4872
4873 if (strcmp(codec->chip_name, "ALC271X"))
4874 return;
4875 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4876 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4877 snd_hda_sequence_write(codec, verbs);
4878}
4879
4880enum {
4881 ALC269_FIXUP_SONY_VAIO,
4882 ALC275_FIXUP_SONY_VAIO_GPIO2,
4883 ALC269_FIXUP_DELL_M101Z,
4884 ALC269_FIXUP_SKU_IGNORE,
4885 ALC269_FIXUP_ASUS_G73JW,
4886 ALC269_FIXUP_LENOVO_EAPD,
4887 ALC275_FIXUP_SONY_HWEQ,
4888 ALC271_FIXUP_DMIC,
4889};
4890
4891static const struct alc_fixup alc269_fixups[] = {
4892 [ALC269_FIXUP_SONY_VAIO] = {
4893 .type = ALC_FIXUP_VERBS,
4894 .v.verbs = (const struct hda_verb[]) {
4895 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4896 {}
4897 }
4898 },
4899 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4900 .type = ALC_FIXUP_VERBS,
4901 .v.verbs = (const struct hda_verb[]) {
4902 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4903 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4904 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4905 { }
4906 },
4907 .chained = true,
4908 .chain_id = ALC269_FIXUP_SONY_VAIO
4909 },
4910 [ALC269_FIXUP_DELL_M101Z] = {
4911 .type = ALC_FIXUP_VERBS,
4912 .v.verbs = (const struct hda_verb[]) {
4913 /* Enables internal speaker */
4914 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4915 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4916 {}
4917 }
4918 },
4919 [ALC269_FIXUP_SKU_IGNORE] = {
4920 .type = ALC_FIXUP_SKU,
4921 .v.sku = ALC_FIXUP_SKU_IGNORE,
4922 },
4923 [ALC269_FIXUP_ASUS_G73JW] = {
4924 .type = ALC_FIXUP_PINS,
4925 .v.pins = (const struct alc_pincfg[]) {
4926 { 0x17, 0x99130111 }, /* subwoofer */
4927 { }
4928 }
4929 },
4930 [ALC269_FIXUP_LENOVO_EAPD] = {
4931 .type = ALC_FIXUP_VERBS,
4932 .v.verbs = (const struct hda_verb[]) {
4933 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4934 {}
4935 }
4936 },
4937 [ALC275_FIXUP_SONY_HWEQ] = {
4938 .type = ALC_FIXUP_FUNC,
4939 .v.func = alc269_fixup_hweq,
4940 .chained = true,
4941 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4942 },
4943 [ALC271_FIXUP_DMIC] = {
4944 .type = ALC_FIXUP_FUNC,
4945 .v.func = alc271_fixup_dmic,
4946 },
4947};
4948
4949static const struct snd_pci_quirk alc269_fixup_tbl[] = {
4950 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4951 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4952 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4953 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4954 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4955 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
4956 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4957 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4958 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4959 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4960 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
4961 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
4962 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
4963 {}
4964};
4965
4966
4967static int alc269_fill_coef(struct hda_codec *codec)
4968{
4969 int val;
4970
4971 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4972 alc_write_coef_idx(codec, 0xf, 0x960b);
4973 alc_write_coef_idx(codec, 0xe, 0x8817);
4974 }
4975
4976 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4977 alc_write_coef_idx(codec, 0xf, 0x960b);
4978 alc_write_coef_idx(codec, 0xe, 0x8814);
4979 }
4980
4981 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4982 val = alc_read_coef_idx(codec, 0x04);
4983 /* Power up output pin */
4984 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4985 }
4986
4987 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4988 val = alc_read_coef_idx(codec, 0xd);
4989 if ((val & 0x0c00) >> 10 != 0x1) {
4990 /* Capless ramp up clock control */
4991 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4992 }
4993 val = alc_read_coef_idx(codec, 0x17);
4994 if ((val & 0x01c0) >> 6 != 0x4) {
4995 /* Class D power on reset */
4996 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4997 }
4998 }
4999
5000 val = alc_read_coef_idx(codec, 0xd); /* Class D */
5001 alc_write_coef_idx(codec, 0xd, val | (1<<14));
5002
5003 val = alc_read_coef_idx(codec, 0x4); /* HP */
5004 alc_write_coef_idx(codec, 0x4, val | (1<<11));
5005
5006 return 0;
5007}
5008
5009/*
5010 */
5011#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5012#include "alc269_quirks.c"
5013#endif
5014
5015static int patch_alc269(struct hda_codec *codec)
5016{
5017 struct alc_spec *spec;
5018 int board_config, coef;
5019 int err;
5020
5021 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5022 if (spec == NULL)
5023 return -ENOMEM;
5024
5025 codec->spec = spec;
5026
5027 spec->mixer_nid = 0x0b;
5028
5029 alc_auto_parse_customize_define(codec);
5030
5031 if (codec->vendor_id == 0x10ec0269) {
5032 spec->codec_variant = ALC269_TYPE_ALC269VA;
5033 coef = alc_read_coef_idx(codec, 0);
5034 if ((coef & 0x00f0) == 0x0010) {
5035 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
5036 spec->cdefine.platform_type == 1) {
5037 alc_codec_rename(codec, "ALC271X");
5038 } else if ((coef & 0xf000) == 0x2000) {
5039 alc_codec_rename(codec, "ALC259");
5040 } else if ((coef & 0xf000) == 0x3000) {
5041 alc_codec_rename(codec, "ALC258");
5042 } else if ((coef & 0xfff0) == 0x3010) {
5043 alc_codec_rename(codec, "ALC277");
5044 } else {
5045 alc_codec_rename(codec, "ALC269VB");
5046 }
5047 spec->codec_variant = ALC269_TYPE_ALC269VB;
5048 } else if ((coef & 0x00f0) == 0x0020) {
5049 if (coef == 0xa023)
5050 alc_codec_rename(codec, "ALC259");
5051 else if (coef == 0x6023)
5052 alc_codec_rename(codec, "ALC281X");
5053 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
5054 codec->bus->pci->subsystem_device == 0x21f3)
5055 alc_codec_rename(codec, "ALC3202");
5056 else
5057 alc_codec_rename(codec, "ALC269VC");
5058 spec->codec_variant = ALC269_TYPE_ALC269VC;
5059 } else
5060 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5061 alc269_fill_coef(codec);
5062 }
5063
5064 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
5065 alc269_models, alc269_cfg_tbl);
5066
5067 if (board_config < 0) {
5068 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5069 codec->chip_name);
5070 board_config = ALC_MODEL_AUTO;
5071 }
5072
5073 if (board_config == ALC_MODEL_AUTO) {
5074 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
5075 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5076 }
5077
5078 if (board_config == ALC_MODEL_AUTO) {
5079 /* automatic parse from the BIOS config */
5080 err = alc269_parse_auto_config(codec);
5081 if (err < 0) {
5082 alc_free(codec);
5083 return err;
5084 }
5085#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5086 else if (!err) {
5087 printk(KERN_INFO
5088 "hda_codec: Cannot set up configuration "
5089 "from BIOS. Using base mode...\n");
5090 board_config = ALC269_BASIC;
5091 }
5092#endif
5093 }
5094
5095 if (has_cdefine_beep(codec)) {
5096 err = snd_hda_attach_beep_device(codec, 0x1);
5097 if (err < 0) {
5098 alc_free(codec);
5099 return err;
5100 }
5101 }
5102
5103 if (board_config != ALC_MODEL_AUTO)
5104 setup_preset(codec, &alc269_presets[board_config]);
5105
5106#if 0
5107 if (board_config == ALC269_QUANTA_FL1) {
5108 /* Due to a hardware problem on Lenovo Ideadpad, we need to
5109 * fix the sample rate of analog I/O to 44.1kHz
5110 */
5111 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
5112 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
5113 }
5114#endif
5115
5116 if (!spec->adc_nids) { /* wasn't filled automatically? use default */
5117 alc_auto_fill_adc_caps(codec);
5118 alc_rebuild_imux_for_auto_mic(codec);
5119 alc_remove_invalid_adc_nids(codec);
5120 }
5121
5122 if (!spec->cap_mixer)
5123 set_capture_mixer(codec);
5124 if (has_cdefine_beep(codec))
5125 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5126
5127 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5128
5129 spec->vmaster_nid = 0x02;
5130
5131 codec->patch_ops = alc_patch_ops;
5132#ifdef SND_HDA_NEEDS_RESUME
5133 codec->patch_ops.resume = alc269_resume;
5134#endif
5135 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02005136 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005137 spec->shutup = alc269_shutup;
5138
5139 alc_init_jacks(codec);
5140#ifdef CONFIG_SND_HDA_POWER_SAVE
5141 if (!spec->loopback.amplist)
5142 spec->loopback.amplist = alc269_loopbacks;
5143 if (alc269_mic2_for_mute_led(codec))
5144 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
5145#endif
5146
5147 return 0;
5148}
5149
5150/*
5151 * ALC861
5152 */
5153
Takashi Iwai1d045db2011-07-07 18:23:21 +02005154static int alc861_parse_auto_config(struct hda_codec *codec)
5155{
5156 struct alc_spec *spec = codec->spec;
5157 int err;
5158 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
5159
5160 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5161 alc861_ignore);
5162 if (err < 0)
5163 return err;
5164 if (!spec->autocfg.line_outs)
5165 return 0; /* can't find valid BIOS pin config */
5166
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02005167 err = alc_auto_fill_dac_nids(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005168 if (err < 0)
5169 return err;
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02005170 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005171 if (err < 0)
5172 return err;
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02005173 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005174 if (err < 0)
5175 return err;
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02005176 err = alc_auto_create_hp_out(codec);
5177 if (err < 0)
5178 return err;
5179 err = alc_auto_create_speaker_out(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005180 if (err < 0)
5181 return err;
5182 err = alc_auto_create_input_ctls(codec);
5183 if (err < 0)
5184 return err;
5185
5186 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5187
5188 alc_auto_parse_digital(codec);
5189
5190 if (spec->kctls.list)
5191 add_mixer(spec, spec->kctls.list);
5192
5193 alc_remove_invalid_adc_nids(codec);
5194
5195 alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
5196 alc_auto_check_switches(codec);
5197
5198 set_capture_mixer(codec);
5199
5200 return 1;
5201}
5202
Takashi Iwai1d045db2011-07-07 18:23:21 +02005203#ifdef CONFIG_SND_HDA_POWER_SAVE
5204static const struct hda_amp_list alc861_loopbacks[] = {
5205 { 0x15, HDA_INPUT, 0 },
5206 { 0x15, HDA_INPUT, 1 },
5207 { 0x15, HDA_INPUT, 2 },
5208 { 0x15, HDA_INPUT, 3 },
5209 { } /* end */
5210};
5211#endif
5212
5213
5214/* Pin config fixes */
5215enum {
5216 PINFIX_FSC_AMILO_PI1505,
5217};
5218
5219static const struct alc_fixup alc861_fixups[] = {
5220 [PINFIX_FSC_AMILO_PI1505] = {
5221 .type = ALC_FIXUP_PINS,
5222 .v.pins = (const struct alc_pincfg[]) {
5223 { 0x0b, 0x0221101f }, /* HP */
5224 { 0x0f, 0x90170310 }, /* speaker */
5225 { }
5226 }
5227 },
5228};
5229
5230static const struct snd_pci_quirk alc861_fixup_tbl[] = {
5231 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
5232 {}
5233};
5234
5235/*
5236 */
5237#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5238#include "alc861_quirks.c"
5239#endif
5240
5241static int patch_alc861(struct hda_codec *codec)
5242{
5243 struct alc_spec *spec;
5244 int board_config;
5245 int err;
5246
5247 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5248 if (spec == NULL)
5249 return -ENOMEM;
5250
5251 codec->spec = spec;
5252
5253 spec->mixer_nid = 0x15;
5254
5255 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
5256 alc861_models, alc861_cfg_tbl);
5257
5258 if (board_config < 0) {
5259 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5260 codec->chip_name);
5261 board_config = ALC_MODEL_AUTO;
5262 }
5263
5264 if (board_config == ALC_MODEL_AUTO) {
5265 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
5266 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5267 }
5268
5269 if (board_config == ALC_MODEL_AUTO) {
5270 /* automatic parse from the BIOS config */
5271 err = alc861_parse_auto_config(codec);
5272 if (err < 0) {
5273 alc_free(codec);
5274 return err;
5275 }
5276#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5277 else if (!err) {
5278 printk(KERN_INFO
5279 "hda_codec: Cannot set up configuration "
5280 "from BIOS. Using base mode...\n");
5281 board_config = ALC861_3ST_DIG;
5282 }
5283#endif
5284 }
5285
5286 err = snd_hda_attach_beep_device(codec, 0x23);
5287 if (err < 0) {
5288 alc_free(codec);
5289 return err;
5290 }
5291
5292 if (board_config != ALC_MODEL_AUTO)
5293 setup_preset(codec, &alc861_presets[board_config]);
5294
5295 if (!spec->adc_nids) {
5296 alc_auto_fill_adc_caps(codec);
5297 alc_rebuild_imux_for_auto_mic(codec);
5298 alc_remove_invalid_adc_nids(codec);
5299 }
5300
5301 if (!spec->cap_mixer)
5302 set_capture_mixer(codec);
5303 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
5304
5305 spec->vmaster_nid = 0x03;
5306
5307 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5308
5309 codec->patch_ops = alc_patch_ops;
5310 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02005311 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005312#ifdef CONFIG_SND_HDA_POWER_SAVE
5313 spec->power_hook = alc_power_eapd;
5314#endif
5315 }
5316#ifdef CONFIG_SND_HDA_POWER_SAVE
5317 if (!spec->loopback.amplist)
5318 spec->loopback.amplist = alc861_loopbacks;
5319#endif
5320
5321 return 0;
5322}
5323
5324/*
5325 * ALC861-VD support
5326 *
5327 * Based on ALC882
5328 *
5329 * In addition, an independent DAC
5330 */
5331#ifdef CONFIG_SND_HDA_POWER_SAVE
5332#define alc861vd_loopbacks alc880_loopbacks
5333#endif
5334
Takashi Iwai1d045db2011-07-07 18:23:21 +02005335static int alc861vd_parse_auto_config(struct hda_codec *codec)
5336{
5337 struct alc_spec *spec = codec->spec;
5338 int err;
5339 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
5340
5341 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5342 alc861vd_ignore);
5343 if (err < 0)
5344 return err;
5345 if (!spec->autocfg.line_outs)
5346 return 0; /* can't find valid BIOS pin config */
5347
5348 err = alc_auto_fill_dac_nids(codec);
5349 if (err < 0)
5350 return err;
5351 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
5352 if (err < 0)
5353 return err;
Takashi Iwaia1f649d2011-07-08 14:39:03 +02005354 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005355 if (err < 0)
5356 return err;
Takashi Iwaia1f649d2011-07-08 14:39:03 +02005357 err = alc_auto_create_hp_out(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005358 if (err < 0)
5359 return err;
Takashi Iwaia1f649d2011-07-08 14:39:03 +02005360 err = alc_auto_create_speaker_out(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005361 if (err < 0)
5362 return err;
5363 err = alc_auto_create_input_ctls(codec);
5364 if (err < 0)
5365 return err;
5366
5367 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5368
5369 alc_auto_parse_digital(codec);
5370
5371 if (spec->kctls.list)
5372 add_mixer(spec, spec->kctls.list);
5373
5374 alc_remove_invalid_adc_nids(codec);
5375
5376 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
5377 alc_auto_check_switches(codec);
5378
5379 err = alc_auto_add_mic_boost(codec);
5380 if (err < 0)
5381 return err;
5382
5383 return 1;
5384}
5385
Takashi Iwai1d045db2011-07-07 18:23:21 +02005386enum {
5387 ALC660VD_FIX_ASUS_GPIO1
5388};
5389
5390/* reset GPIO1 */
5391static const struct alc_fixup alc861vd_fixups[] = {
5392 [ALC660VD_FIX_ASUS_GPIO1] = {
5393 .type = ALC_FIXUP_VERBS,
5394 .v.verbs = (const struct hda_verb[]) {
5395 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5396 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5397 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5398 { }
5399 }
5400 },
5401};
5402
5403static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
5404 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
5405 {}
5406};
5407
5408static const struct hda_verb alc660vd_eapd_verbs[] = {
5409 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
5410 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
5411 { }
5412};
5413
5414/*
5415 */
5416#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5417#include "alc861vd_quirks.c"
5418#endif
5419
5420static int patch_alc861vd(struct hda_codec *codec)
5421{
5422 struct alc_spec *spec;
5423 int err, board_config;
5424
5425 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5426 if (spec == NULL)
5427 return -ENOMEM;
5428
5429 codec->spec = spec;
5430
5431 spec->mixer_nid = 0x0b;
5432
5433 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
5434 alc861vd_models, alc861vd_cfg_tbl);
5435
5436 if (board_config < 0) {
5437 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5438 codec->chip_name);
5439 board_config = ALC_MODEL_AUTO;
5440 }
5441
5442 if (board_config == ALC_MODEL_AUTO) {
5443 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
5444 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5445 }
5446
5447 if (board_config == ALC_MODEL_AUTO) {
5448 /* automatic parse from the BIOS config */
5449 err = alc861vd_parse_auto_config(codec);
5450 if (err < 0) {
5451 alc_free(codec);
5452 return err;
5453 }
5454#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5455 else if (!err) {
5456 printk(KERN_INFO
5457 "hda_codec: Cannot set up configuration "
5458 "from BIOS. Using base mode...\n");
5459 board_config = ALC861VD_3ST;
5460 }
5461#endif
5462 }
5463
5464 err = snd_hda_attach_beep_device(codec, 0x23);
5465 if (err < 0) {
5466 alc_free(codec);
5467 return err;
5468 }
5469
5470 if (board_config != ALC_MODEL_AUTO)
5471 setup_preset(codec, &alc861vd_presets[board_config]);
5472
5473 if (codec->vendor_id == 0x10ec0660) {
5474 /* always turn on EAPD */
5475 add_verb(spec, alc660vd_eapd_verbs);
5476 }
5477
5478 if (!spec->adc_nids) {
5479 alc_auto_fill_adc_caps(codec);
5480 alc_rebuild_imux_for_auto_mic(codec);
5481 alc_remove_invalid_adc_nids(codec);
5482 }
5483
5484 set_capture_mixer(codec);
5485 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5486
5487 spec->vmaster_nid = 0x02;
5488
5489 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5490
5491 codec->patch_ops = alc_patch_ops;
5492
5493 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005494 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005495 spec->shutup = alc_eapd_shutup;
5496#ifdef CONFIG_SND_HDA_POWER_SAVE
5497 if (!spec->loopback.amplist)
5498 spec->loopback.amplist = alc861vd_loopbacks;
5499#endif
5500
5501 return 0;
5502}
5503
5504/*
5505 * ALC662 support
5506 *
5507 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5508 * configuration. Each pin widget can choose any input DACs and a mixer.
5509 * Each ADC is connected from a mixer of all inputs. This makes possible
5510 * 6-channel independent captures.
5511 *
5512 * In addition, an independent DAC for the multi-playback (not used in this
5513 * driver yet).
5514 */
5515#ifdef CONFIG_SND_HDA_POWER_SAVE
5516#define alc662_loopbacks alc880_loopbacks
5517#endif
5518
5519/*
5520 * BIOS auto configuration
5521 */
5522
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005523static int alc662_parse_auto_config(struct hda_codec *codec)
5524{
5525 struct alc_spec *spec = codec->spec;
5526 int err;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005527 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005528
5529 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5530 alc662_ignore);
5531 if (err < 0)
5532 return err;
5533 if (!spec->autocfg.line_outs)
5534 return 0; /* can't find valid BIOS pin config */
5535
Takashi Iwai343a04b2011-07-06 14:28:39 +02005536 err = alc_auto_fill_dac_nids(codec);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005537 if (err < 0)
5538 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02005539 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
Takashi Iwaice764ab2011-04-27 16:35:23 +02005540 if (err < 0)
5541 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02005542 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005543 if (err < 0)
5544 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02005545 err = alc_auto_create_extra_out(codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005546 spec->autocfg.speaker_pins[0],
Takashi Iwai3af9ee62011-06-27 12:34:01 +02005547 spec->multiout.extra_out_nid[0],
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005548 "Speaker");
5549 if (err < 0)
5550 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02005551 err = alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
Takashi Iwai3af9ee62011-06-27 12:34:01 +02005552 spec->multiout.hp_nid,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005553 "Headphone");
5554 if (err < 0)
5555 return err;
Takashi Iwaib7821702011-07-06 15:12:46 +02005556 err = alc_auto_create_input_ctls(codec);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005557 if (err < 0)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005558 return err;
5559
5560 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5561
Takashi Iwai757899a2010-07-30 10:48:14 +02005562 alc_auto_parse_digital(codec);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005563
Takashi Iwai603c4012008-07-30 15:01:44 +02005564 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +01005565 add_mixer(spec, spec->kctls.list);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005566
Takashi Iwai21268962011-07-07 15:01:13 +02005567 alc_remove_invalid_adc_nids(codec);
Takashi Iwaiee979a142008-09-02 15:42:20 +02005568
Kailang Yang6227cdc2010-02-25 08:36:52 +01005569 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5570 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
5571 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
5572 else
5573 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai21268962011-07-07 15:01:13 +02005574 alc_auto_check_switches(codec);
5575
5576 err = alc_auto_add_mic_boost(codec);
5577 if (err < 0)
5578 return err;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02005579
Takashi Iwai8c872862007-06-19 12:11:16 +02005580 return 1;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005581}
5582
Todd Broch6be79482010-12-07 16:51:05 -08005583static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005584 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005585{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005586 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005587 return;
Todd Broch6be79482010-12-07 16:51:05 -08005588 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5589 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5590 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5591 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5592 (0 << AC_AMPCAP_MUTE_SHIFT)))
5593 printk(KERN_WARNING
5594 "hda_codec: failed to override amp caps for NID 0x2\n");
5595}
5596
David Henningsson6cb3b702010-09-09 08:51:44 +02005597enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005598 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005599 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005600 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005601 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005602 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005603 ALC662_FIXUP_HP_RP5800,
David Henningsson6cb3b702010-09-09 08:51:44 +02005604};
5605
5606static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005607 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005608 .type = ALC_FIXUP_PINS,
5609 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005610 { 0x15, 0x99130112 }, /* subwoofer */
5611 { }
5612 }
5613 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005614 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005615 .type = ALC_FIXUP_PINS,
5616 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005617 { 0x17, 0x99130112 }, /* subwoofer */
5618 { }
5619 }
5620 },
Todd Broch6be79482010-12-07 16:51:05 -08005621 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005622 .type = ALC_FIXUP_FUNC,
5623 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005624 },
5625 [ALC662_FIXUP_CZC_P10T] = {
5626 .type = ALC_FIXUP_VERBS,
5627 .v.verbs = (const struct hda_verb[]) {
5628 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5629 {}
5630 }
5631 },
David Henningsson94024cd2011-04-29 14:10:55 +02005632 [ALC662_FIXUP_SKU_IGNORE] = {
5633 .type = ALC_FIXUP_SKU,
5634 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005635 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005636 [ALC662_FIXUP_HP_RP5800] = {
5637 .type = ALC_FIXUP_PINS,
5638 .v.pins = (const struct alc_pincfg[]) {
5639 { 0x14, 0x0221201f }, /* HP out */
5640 { }
5641 },
5642 .chained = true,
5643 .chain_id = ALC662_FIXUP_SKU_IGNORE
5644 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005645};
5646
Takashi Iwaia9111322011-05-02 11:30:18 +02005647static const struct snd_pci_quirk alc662_fixup_tbl[] = {
David Henningssona6c47a82011-02-10 15:39:19 +01005648 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005649 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005650 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005651 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005652 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005653 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005654 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005655 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02005656 {}
5657};
5658
Todd Broch6be79482010-12-07 16:51:05 -08005659static const struct alc_model_fixup alc662_fixup_models[] = {
5660 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
5661 {}
5662};
David Henningsson6cb3b702010-09-09 08:51:44 +02005663
5664
Takashi Iwai1d045db2011-07-07 18:23:21 +02005665/*
5666 */
5667#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5668#include "alc662_quirks.c"
5669#endif
5670
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005671static int patch_alc662(struct hda_codec *codec)
5672{
5673 struct alc_spec *spec;
5674 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02005675 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005676
5677 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5678 if (!spec)
5679 return -ENOMEM;
5680
5681 codec->spec = spec;
5682
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005683 spec->mixer_nid = 0x0b;
5684
Kailang Yangda00c242010-03-19 11:23:45 +01005685 alc_auto_parse_customize_define(codec);
5686
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005687 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5688
Kailang Yang693194f2010-10-21 08:51:48 +02005689 coef = alc_read_coef_idx(codec, 0);
5690 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005691 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005692 else if (coef & (1 << 14) &&
5693 codec->bus->pci->subsystem_vendor == 0x1025 &&
5694 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005695 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005696 else if (coef == 0x4011)
5697 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005698
Takashi Iwai1d045db2011-07-07 18:23:21 +02005699 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
5700 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005701 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005702 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5703 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005704 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005705 }
5706
Takashi Iwai1d045db2011-07-07 18:23:21 +02005707 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005708 alc_pick_fixup(codec, alc662_fixup_models,
5709 alc662_fixup_tbl, alc662_fixups);
5710 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005711 /* automatic parse from the BIOS config */
5712 err = alc662_parse_auto_config(codec);
5713 if (err < 0) {
5714 alc_free(codec);
5715 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005716 }
5717#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5718 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005719 printk(KERN_INFO
5720 "hda_codec: Cannot set up configuration "
5721 "from BIOS. Using base mode...\n");
5722 board_config = ALC662_3ST_2ch_DIG;
5723 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005724#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005725 }
5726
Takashi Iwaidc1eae22010-07-29 15:30:02 +02005727 if (has_cdefine_beep(codec)) {
Takashi Iwai8af25912010-07-28 17:37:16 +02005728 err = snd_hda_attach_beep_device(codec, 0x1);
5729 if (err < 0) {
5730 alc_free(codec);
5731 return err;
5732 }
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09005733 }
5734
Takashi Iwai1d045db2011-07-07 18:23:21 +02005735 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005736 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005737
Takashi Iwaidd704692009-08-11 08:45:11 +02005738 if (!spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005739 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005740 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005741 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005742 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005743
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005744 if (!spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005745 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005746
Takashi Iwaidc1eae22010-07-29 15:30:02 +02005747 if (has_cdefine_beep(codec)) {
Kailang Yangda00c242010-03-19 11:23:45 +01005748 switch (codec->vendor_id) {
5749 case 0x10ec0662:
5750 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5751 break;
5752 case 0x10ec0272:
5753 case 0x10ec0663:
5754 case 0x10ec0665:
5755 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5756 break;
5757 case 0x10ec0273:
5758 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5759 break;
5760 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005761 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005762 spec->vmaster_nid = 0x02;
5763
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005764 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5765
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005766 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005767 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005768 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c716152011-04-07 10:37:16 +02005769 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005770
Kailang Yangbf1b0222010-10-21 08:49:56 +02005771 alc_init_jacks(codec);
5772
Takashi Iwaicb53c622007-08-10 17:21:45 +02005773#ifdef CONFIG_SND_HDA_POWER_SAVE
5774 if (!spec->loopback.amplist)
5775 spec->loopback.amplist = alc662_loopbacks;
5776#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005777
5778 return 0;
5779}
5780
Kailang Yang274693f2009-12-03 10:07:50 +01005781static int patch_alc888(struct hda_codec *codec)
5782{
5783 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5784 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005785 if (codec->vendor_id == 0x10ec0887)
5786 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5787 else
5788 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005789 if (!codec->chip_name) {
5790 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005791 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005792 }
5793 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005794 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005795 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005796}
5797
Kailang Yangb478b992011-05-18 11:51:15 +02005798static int patch_alc899(struct hda_codec *codec)
5799{
5800 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5801 kfree(codec->chip_name);
5802 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5803 }
5804 return patch_alc882(codec);
5805}
5806
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005807/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005808 * ALC680 support
5809 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005810
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005811static int alc680_parse_auto_config(struct hda_codec *codec)
5812{
5813 struct alc_spec *spec = codec->spec;
5814 int err;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005815 static const hda_nid_t alc680_ignore[] = { 0 };
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005816
5817 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5818 alc680_ignore);
5819 if (err < 0)
5820 return err;
Kailang Yangc69aefa2010-08-17 10:39:22 +02005821
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005822 if (!spec->autocfg.line_outs) {
5823 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
5824 spec->multiout.max_channels = 2;
5825 spec->no_analog = 1;
5826 goto dig_only;
5827 }
5828 return 0; /* can't find valid BIOS pin config */
5829 }
Takashi Iwaiafcd5512011-07-08 11:07:59 +02005830
5831 err = alc_auto_fill_dac_nids(codec);
5832 if (err < 0)
5833 return err;
5834
5835 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
5836 if (err < 0)
5837 return err;
5838
5839 err = alc_auto_create_hp_out(codec);
5840 if (err < 0)
5841 return err;
5842
5843 err = alc_auto_create_speaker_out(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005844 if (err < 0)
5845 return err;
5846
Takashi Iwai21268962011-07-07 15:01:13 +02005847 err = alc_auto_create_input_ctls(codec);
5848 if (err < 0)
5849 return err;
5850
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005851 spec->multiout.max_channels = 2;
5852
5853 dig_only:
5854 /* digital only support output */
Takashi Iwai757899a2010-07-30 10:48:14 +02005855 alc_auto_parse_digital(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005856 if (spec->kctls.list)
5857 add_mixer(spec, spec->kctls.list);
5858
Takashi Iwai21268962011-07-07 15:01:13 +02005859 alc_remove_invalid_adc_nids(codec);
5860
5861 alc_auto_check_switches(codec);
5862
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005863 err = alc_auto_add_mic_boost(codec);
5864 if (err < 0)
5865 return err;
5866
5867 return 1;
5868}
5869
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005870/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005871 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005872#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5873#include "alc680_quirks.c"
5874#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005875
5876static int patch_alc680(struct hda_codec *codec)
5877{
5878 struct alc_spec *spec;
5879 int board_config;
5880 int err;
5881
5882 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5883 if (spec == NULL)
5884 return -ENOMEM;
5885
5886 codec->spec = spec;
5887
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005888 /* ALC680 has no aa-loopback mixer */
5889
Takashi Iwai1d045db2011-07-07 18:23:21 +02005890 board_config = alc_board_config(codec, ALC680_MODEL_LAST,
5891 alc680_models, alc680_cfg_tbl);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005892
Takashi Iwai1d045db2011-07-07 18:23:21 +02005893 if (board_config < 0) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005894 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5895 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005896 board_config = ALC_MODEL_AUTO;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005897 }
5898
Takashi Iwai1d045db2011-07-07 18:23:21 +02005899 if (board_config == ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005900 /* automatic parse from the BIOS config */
5901 err = alc680_parse_auto_config(codec);
5902 if (err < 0) {
5903 alc_free(codec);
5904 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005905 }
5906#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5907 else if (!err) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005908 printk(KERN_INFO
5909 "hda_codec: Cannot set up configuration "
5910 "from BIOS. Using base mode...\n");
5911 board_config = ALC680_BASE;
5912 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005913#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005914 }
5915
Takashi Iwai1d045db2011-07-07 18:23:21 +02005916 if (board_config != ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005917 setup_preset(codec, &alc680_presets[board_config]);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005918#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
Takashi Iwai21268962011-07-07 15:01:13 +02005919 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005920#endif
Takashi Iwai21268962011-07-07 15:01:13 +02005921 }
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005922
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005923 if (!spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005924 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005925 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005926 alc_remove_invalid_adc_nids(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005927 }
5928
5929 if (!spec->cap_mixer)
5930 set_capture_mixer(codec);
5931
5932 spec->vmaster_nid = 0x02;
5933
5934 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005935 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005936 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005937
5938 return 0;
5939}
5940
5941/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942 * patch entries
5943 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005944static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005945 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005946 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005947 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005948 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005949 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005950 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005951 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005952 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005953 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005954 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005955 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005956 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005957 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5958 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5959 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005960 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +02005961 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005962 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5963 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005964 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005965 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005966 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005967 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005968 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +02005970 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005971 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005972 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005973 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005974 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005975 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005976 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005977 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +02005978 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005979 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai49535502009-06-30 15:28:30 +02005980 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005981 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005982 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005983 {} /* terminator */
5984};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005985
5986MODULE_ALIAS("snd-hda-codec-id:10ec*");
5987
5988MODULE_LICENSE("GPL");
5989MODULE_DESCRIPTION("Realtek HD-audio codec");
5990
5991static struct hda_codec_preset_list realtek_list = {
5992 .preset = snd_hda_preset_realtek,
5993 .owner = THIS_MODULE,
5994};
5995
5996static int __init patch_realtek_init(void)
5997{
5998 return snd_hda_add_codec_preset(&realtek_list);
5999}
6000
6001static void __exit patch_realtek_exit(void)
6002{
6003 snd_hda_delete_codec_preset(&realtek_list);
6004}
6005
6006module_init(patch_realtek_init)
6007module_exit(patch_realtek_exit)