blob: a29e6b3c6a70457f705b6a521cc3ee89e51d6219 [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
209/*
210 * input MUX handling
211 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200212static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
213 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
215 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
216 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200217 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
218 if (mux_idx >= spec->num_mux_defs)
219 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100220 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
221 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200222 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223}
224
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200225static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
226 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227{
228 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
229 struct alc_spec *spec = codec->spec;
230 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
231
232 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
233 return 0;
234}
235
Takashi Iwai21268962011-07-07 15:01:13 +0200236static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
Takashi Iwai21268962011-07-07 15:01:13 +0200238 struct alc_spec *spec = codec->spec;
239 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
240
241 if (spec->cur_adc && spec->cur_adc != new_adc) {
242 /* stream is running, let's swap the current ADC */
243 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
244 spec->cur_adc = new_adc;
245 snd_hda_codec_setup_stream(codec, new_adc,
246 spec->cur_adc_stream_tag, 0,
247 spec->cur_adc_format);
248 return true;
249 }
250 return false;
251}
252
253/* select the given imux item; either unmute exclusively or select the route */
254static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
255 unsigned int idx, bool force)
256{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100258 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100259 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200260 int i, type;
261 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Takashi Iwaicd896c32008-11-18 12:36:33 +0100263 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
264 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100265 if (!imux->num_items && mux_idx > 0)
266 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100267
Takashi Iwai21268962011-07-07 15:01:13 +0200268 if (idx >= imux->num_items)
269 idx = imux->num_items - 1;
270 if (spec->cur_mux[adc_idx] == idx && !force)
271 return 0;
272 spec->cur_mux[adc_idx] = idx;
273
274 if (spec->dyn_adc_switch) {
275 alc_dyn_adc_pcm_resetup(codec, idx);
276 adc_idx = spec->dyn_adc_idx[idx];
277 }
278
279 nid = spec->capsrc_nids ?
280 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
281
282 /* no selection? */
283 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
284 return 1;
285
Takashi Iwaia22d5432009-07-27 12:54:26 +0200286 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200287 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100288 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100289 for (i = 0; i < imux->num_items; i++) {
290 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
291 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
292 imux->items[i].index,
293 HDA_AMP_MUTE, v);
294 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100295 } else {
296 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200297 snd_hda_codec_write_cache(codec, nid, 0,
298 AC_VERB_SET_CONNECT_SEL,
299 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100300 }
Takashi Iwai21268962011-07-07 15:01:13 +0200301 return 1;
302}
303
304static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
305 struct snd_ctl_elem_value *ucontrol)
306{
307 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
308 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
309 return alc_mux_select(codec, adc_idx,
310 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100311}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100314 * set up the input pin config (depending on the given auto-pin type)
315 */
316static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
317 int auto_pin_type)
318{
319 unsigned int val = PIN_IN;
320
Takashi Iwai86e29592010-09-09 14:50:17 +0200321 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100322 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200323 unsigned int oldval;
324 oldval = snd_hda_codec_read(codec, nid, 0,
325 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100326 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100327 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200328 /* if the default pin setup is vref50, we give it priority */
329 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100330 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200331 else if (pincap & AC_PINCAP_VREF_50)
332 val = PIN_VREF50;
333 else if (pincap & AC_PINCAP_VREF_100)
334 val = PIN_VREF100;
335 else if (pincap & AC_PINCAP_VREF_GRD)
336 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100337 }
338 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
339}
340
341/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200342 * Append the given mixer and verb elements for the later use
343 * The mixer array is referred in build_controls(), and init_verbs are
344 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100345 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200346static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100347{
348 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
349 return;
350 spec->mixers[spec->num_mixers++] = mix;
351}
352
353static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
354{
355 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
356 return;
357 spec->init_verbs[spec->num_init_verbs++] = verb;
358}
359
360/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200361 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100362 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200363/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200364static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200365 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
366 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
367 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
368 { }
369};
370
Takashi Iwaia9111322011-05-02 11:30:18 +0200371static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200372 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
373 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
374 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
375 { }
376};
377
Takashi Iwaia9111322011-05-02 11:30:18 +0200378static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200379 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
380 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
381 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
382 { }
383};
384
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200385/*
386 * Fix hardware PLL issue
387 * On some codecs, the analog PLL gating control must be off while
388 * the default value is 1.
389 */
390static void alc_fix_pll(struct hda_codec *codec)
391{
392 struct alc_spec *spec = codec->spec;
393 unsigned int val;
394
395 if (!spec->pll_nid)
396 return;
397 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
398 spec->pll_coef_idx);
399 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
400 AC_VERB_GET_PROC_COEF, 0);
401 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
402 spec->pll_coef_idx);
403 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
404 val & ~(1 << spec->pll_coef_bit));
405}
406
407static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
408 unsigned int coef_idx, unsigned int coef_bit)
409{
410 struct alc_spec *spec = codec->spec;
411 spec->pll_nid = nid;
412 spec->pll_coef_idx = coef_idx;
413 spec->pll_coef_bit = coef_bit;
414 alc_fix_pll(codec);
415}
416
Takashi Iwai1d045db2011-07-07 18:23:21 +0200417/*
418 * Jack-reporting via input-jack layer
419 */
420
421/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200422static int alc_init_jacks(struct hda_codec *codec)
423{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100424#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200425 struct alc_spec *spec = codec->spec;
426 int err;
427 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200428 unsigned int mic_nid = spec->ext_mic_pin;
429 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200430
Takashi Iwai265a0242010-09-21 11:26:21 +0200431 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100432 err = snd_hda_input_jack_add(codec, hp_nid,
433 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200434 if (err < 0)
435 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100436 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200437 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200438
Takashi Iwai265a0242010-09-21 11:26:21 +0200439 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100440 err = snd_hda_input_jack_add(codec, mic_nid,
441 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200442 if (err < 0)
443 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100444 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200445 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200446 if (dock_nid) {
447 err = snd_hda_input_jack_add(codec, dock_nid,
448 SND_JACK_MICROPHONE, NULL);
449 if (err < 0)
450 return err;
451 snd_hda_input_jack_report(codec, dock_nid);
452 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100453#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200454 return 0;
455}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200456
Takashi Iwai1d045db2011-07-07 18:23:21 +0200457/*
458 * Jack detections for HP auto-mute and mic-switch
459 */
460
461/* check each pin in the given array; returns true if any of them is plugged */
462static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200463{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200464 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200465
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200466 for (i = 0; i < num_pins; i++) {
467 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200468 if (!nid)
469 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100470 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200471 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200472 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200473 return present;
474}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200475
Takashi Iwai1d045db2011-07-07 18:23:21 +0200476/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200477static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200478 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200479{
480 struct alc_spec *spec = codec->spec;
481 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200482 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200483 int i;
484
485 for (i = 0; i < num_pins; i++) {
486 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200487 if (!nid)
488 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200489 switch (spec->automute_mode) {
490 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200491 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200492 AC_VERB_SET_PIN_WIDGET_CONTROL,
493 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200494 break;
495 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200496 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200497 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200498 break;
499 case ALC_AUTOMUTE_MIXER:
500 nid = spec->automute_mixer_nid[i];
501 if (!nid)
502 break;
503 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200504 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200505 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200506 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200507 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200508 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200509 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200510}
511
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200512/* Toggle internal speakers muting */
513static void update_speakers(struct hda_codec *codec)
514{
515 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200516 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200517
Takashi Iwaic0a20262011-06-10 15:28:15 +0200518 /* Control HP pins/amps depending on master_mute state;
519 * in general, HP pins/amps control should be enabled in all cases,
520 * but currently set only for master_mute, just to be safe
521 */
522 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
523 spec->autocfg.hp_pins, spec->master_mute, true);
524
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200525 if (!spec->automute)
526 on = 0;
527 else
528 on = spec->jack_present | spec->line_jack_present;
529 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200530 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200531 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200532
533 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200534 /* if LO is a copy of either HP or Speaker, don't need to handle it */
535 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
536 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200537 return;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200538 if (!spec->automute_lines || !spec->automute)
539 on = 0;
540 else
541 on = spec->jack_present;
542 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200543 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200544 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200545}
546
Takashi Iwai1d045db2011-07-07 18:23:21 +0200547/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200548static void alc_hp_automute(struct hda_codec *codec)
549{
550 struct alc_spec *spec = codec->spec;
551
552 if (!spec->automute)
553 return;
554 spec->jack_present =
555 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
556 spec->autocfg.hp_pins);
557 update_speakers(codec);
558}
559
Takashi Iwai1d045db2011-07-07 18:23:21 +0200560/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200561static void alc_line_automute(struct hda_codec *codec)
562{
563 struct alc_spec *spec = codec->spec;
564
565 if (!spec->automute || !spec->detect_line)
566 return;
567 spec->line_jack_present =
568 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
569 spec->autocfg.line_out_pins);
570 update_speakers(codec);
571}
572
Takashi Iwai8d087c72011-06-28 12:45:47 +0200573#define get_connection_index(codec, mux, nid) \
574 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200575
Takashi Iwai1d045db2011-07-07 18:23:21 +0200576/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200577static void alc_mic_automute(struct hda_codec *codec)
578{
579 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200580 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200581
Takashi Iwai21268962011-07-07 15:01:13 +0200582 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200583 return;
584 if (snd_BUG_ON(!spec->adc_nids))
585 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200586 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200587 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200588
Takashi Iwai21268962011-07-07 15:01:13 +0200589 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
590 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
591 else if (spec->dock_mic_idx >= 0 &&
592 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
593 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
594 else
595 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200596
Takashi Iwai21268962011-07-07 15:01:13 +0200597 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
598 if (spec->dock_mic_idx >= 0)
599 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200600}
601
Kailang Yangc9b58002007-10-16 14:30:01 +0200602/* unsolicited event for HP jack sensing */
603static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
604{
605 if (codec->vendor_id == 0x10ec0880)
606 res >>= 28;
607 else
608 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200609 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200610 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200611 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200612 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200613 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200614 alc_line_automute(codec);
615 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200616 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200617 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200618 break;
619 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200620}
621
Takashi Iwai1d045db2011-07-07 18:23:21 +0200622/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200623static void alc_inithook(struct hda_codec *codec)
624{
Takashi Iwaid922b512011-04-28 12:18:53 +0200625 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200626 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200627 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200628}
629
Kailang Yangf9423e72008-05-27 12:32:25 +0200630/* additional initialization for ALC888 variants */
631static void alc888_coef_init(struct hda_codec *codec)
632{
633 unsigned int tmp;
634
635 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
636 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
637 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100638 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200639 /* alc888S-VC */
640 snd_hda_codec_read(codec, 0x20, 0,
641 AC_VERB_SET_PROC_COEF, 0x830);
642 else
643 /* alc888-VB */
644 snd_hda_codec_read(codec, 0x20, 0,
645 AC_VERB_SET_PROC_COEF, 0x3030);
646}
647
Takashi Iwai1d045db2011-07-07 18:23:21 +0200648/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200649static void alc889_coef_init(struct hda_codec *codec)
650{
651 unsigned int tmp;
652
653 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
654 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
655 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
656 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
657}
658
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100659/* turn on/off EAPD control (only if available) */
660static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
661{
662 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
663 return;
664 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
665 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
666 on ? 2 : 0);
667}
668
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200669/* turn on/off EAPD controls of the codec */
670static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
671{
672 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200673 static hda_nid_t pins[] = {
674 0x0f, 0x10, 0x14, 0x15, 0
675 };
676 hda_nid_t *p;
677 for (p = pins; *p; p++)
678 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200679}
680
Takashi Iwai1c716152011-04-07 10:37:16 +0200681/* generic shutup callback;
682 * just turning off EPAD and a little pause for avoiding pop-noise
683 */
684static void alc_eapd_shutup(struct hda_codec *codec)
685{
686 alc_auto_setup_eapd(codec, false);
687 msleep(200);
688}
689
Takashi Iwai1d045db2011-07-07 18:23:21 +0200690/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200691static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200692{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200693 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200694
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200695 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200696 switch (type) {
697 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200698 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
699 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200700 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200701 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
702 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200703 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200704 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
705 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200706 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200707 switch (codec->vendor_id) {
708 case 0x10ec0260:
709 snd_hda_codec_write(codec, 0x1a, 0,
710 AC_VERB_SET_COEF_INDEX, 7);
711 tmp = snd_hda_codec_read(codec, 0x1a, 0,
712 AC_VERB_GET_PROC_COEF, 0);
713 snd_hda_codec_write(codec, 0x1a, 0,
714 AC_VERB_SET_COEF_INDEX, 7);
715 snd_hda_codec_write(codec, 0x1a, 0,
716 AC_VERB_SET_PROC_COEF,
717 tmp | 0x2010);
718 break;
719 case 0x10ec0262:
720 case 0x10ec0880:
721 case 0x10ec0882:
722 case 0x10ec0883:
723 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100724 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100725 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200726 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200727 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200728 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200729 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200730 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100731#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200732 case 0x10ec0267:
733 case 0x10ec0268:
734 snd_hda_codec_write(codec, 0x20, 0,
735 AC_VERB_SET_COEF_INDEX, 7);
736 tmp = snd_hda_codec_read(codec, 0x20, 0,
737 AC_VERB_GET_PROC_COEF, 0);
738 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200739 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200740 snd_hda_codec_write(codec, 0x20, 0,
741 AC_VERB_SET_PROC_COEF,
742 tmp | 0x3000);
743 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100744#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200745 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200746 break;
747 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200748}
Kailang Yangea1fb292008-08-26 12:58:38 +0200749
Takashi Iwai1d045db2011-07-07 18:23:21 +0200750/*
751 * Auto-Mute mode mixer enum support
752 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200753static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
754 struct snd_ctl_elem_info *uinfo)
755{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200756 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
757 struct alc_spec *spec = codec->spec;
758 static const char * const texts2[] = {
759 "Disabled", "Enabled"
760 };
761 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200762 "Disabled", "Speaker Only", "Line-Out+Speaker"
763 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200764 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200765
766 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
767 uinfo->count = 1;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200768 if (spec->automute_hp_lo) {
769 uinfo->value.enumerated.items = 3;
770 texts = texts3;
771 } else {
772 uinfo->value.enumerated.items = 2;
773 texts = texts2;
774 }
775 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
776 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200777 strcpy(uinfo->value.enumerated.name,
778 texts[uinfo->value.enumerated.item]);
779 return 0;
780}
781
782static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
783 struct snd_ctl_elem_value *ucontrol)
784{
785 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
786 struct alc_spec *spec = codec->spec;
787 unsigned int val;
788 if (!spec->automute)
789 val = 0;
790 else if (!spec->automute_lines)
791 val = 1;
792 else
793 val = 2;
794 ucontrol->value.enumerated.item[0] = val;
795 return 0;
796}
797
798static int alc_automute_mode_put(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
804 switch (ucontrol->value.enumerated.item[0]) {
805 case 0:
806 if (!spec->automute)
807 return 0;
808 spec->automute = 0;
809 break;
810 case 1:
811 if (spec->automute && !spec->automute_lines)
812 return 0;
813 spec->automute = 1;
814 spec->automute_lines = 0;
815 break;
816 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200817 if (!spec->automute_hp_lo)
818 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200819 if (spec->automute && spec->automute_lines)
820 return 0;
821 spec->automute = 1;
822 spec->automute_lines = 1;
823 break;
824 default:
825 return -EINVAL;
826 }
827 update_speakers(codec);
828 return 1;
829}
830
Takashi Iwaia9111322011-05-02 11:30:18 +0200831static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200832 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
833 .name = "Auto-Mute Mode",
834 .info = alc_automute_mode_info,
835 .get = alc_automute_mode_get,
836 .put = alc_automute_mode_put,
837};
838
Takashi Iwai1d045db2011-07-07 18:23:21 +0200839static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
840{
841 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
842 return snd_array_new(&spec->kctls);
843}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200844
845static int alc_add_automute_mode_enum(struct hda_codec *codec)
846{
847 struct alc_spec *spec = codec->spec;
848 struct snd_kcontrol_new *knew;
849
850 knew = alc_kcontrol_new(spec);
851 if (!knew)
852 return -ENOMEM;
853 *knew = alc_automute_mode_enum;
854 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
855 if (!knew->name)
856 return -ENOMEM;
857 return 0;
858}
859
Takashi Iwai1d045db2011-07-07 18:23:21 +0200860/*
861 * Check the availability of HP/line-out auto-mute;
862 * Set up appropriately if really supported
863 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200864static void alc_init_auto_hp(struct hda_codec *codec)
865{
866 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200867 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200868 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200869 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200870
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200871 if (cfg->hp_pins[0])
872 present++;
873 if (cfg->line_out_pins[0])
874 present++;
875 if (cfg->speaker_pins[0])
876 present++;
877 if (present < 2) /* need two different output types */
878 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200879 if (present == 3)
880 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200881
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200882 if (!cfg->speaker_pins[0]) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200883 memcpy(cfg->speaker_pins, cfg->line_out_pins,
884 sizeof(cfg->speaker_pins));
885 cfg->speaker_outs = cfg->line_outs;
886 }
887
888 if (!cfg->hp_pins[0]) {
889 memcpy(cfg->hp_pins, cfg->line_out_pins,
890 sizeof(cfg->hp_pins));
891 cfg->hp_outs = cfg->line_outs;
892 }
893
894 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200895 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200896 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200897 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200898 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200899 nid);
900 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200901 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200902 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200903 spec->automute = 1;
904 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200905 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200906 if (spec->automute && cfg->line_out_pins[0] &&
907 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
908 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
909 for (i = 0; i < cfg->line_outs; i++) {
910 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200911 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200912 continue;
913 snd_printdd("realtek: Enable Line-Out auto-muting "
914 "on NID 0x%x\n", nid);
915 snd_hda_codec_write_cache(codec, nid, 0,
916 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200917 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200918 spec->detect_line = 1;
919 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200920 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200921 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200922
923 if (spec->automute) {
924 /* create a control for automute mode */
925 alc_add_automute_mode_enum(codec);
926 spec->unsol_event = alc_sku_unsol_event;
927 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200928}
929
Takashi Iwai1d045db2011-07-07 18:23:21 +0200930/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200931static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
932{
933 int i;
934 for (i = 0; i < nums; i++)
935 if (list[i] == nid)
936 return i;
937 return -1;
938}
939
Takashi Iwai1d045db2011-07-07 18:23:21 +0200940/* check whether dynamic ADC-switching is available */
941static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
942{
943 struct alc_spec *spec = codec->spec;
944 struct hda_input_mux *imux = &spec->private_imux[0];
945 int i, n, idx;
946 hda_nid_t cap, pin;
947
948 if (imux != spec->input_mux) /* no dynamic imux? */
949 return false;
950
951 for (n = 0; n < spec->num_adc_nids; n++) {
952 cap = spec->private_capsrc_nids[n];
953 for (i = 0; i < imux->num_items; i++) {
954 pin = spec->imux_pins[i];
955 if (!pin)
956 return false;
957 if (get_connection_index(codec, cap, pin) < 0)
958 break;
959 }
960 if (i >= imux->num_items)
961 return false; /* no ADC-switch is needed */
962 }
963
964 for (i = 0; i < imux->num_items; i++) {
965 pin = spec->imux_pins[i];
966 for (n = 0; n < spec->num_adc_nids; n++) {
967 cap = spec->private_capsrc_nids[n];
968 idx = get_connection_index(codec, cap, pin);
969 if (idx >= 0) {
970 imux->items[i].index = idx;
971 spec->dyn_adc_idx[i] = n;
972 break;
973 }
974 }
975 }
976
977 snd_printdd("realtek: enabling ADC switching\n");
978 spec->dyn_adc_switch = 1;
979 return true;
980}
Takashi Iwai21268962011-07-07 15:01:13 +0200981
982/* rebuild imux for matching with the given auto-mic pins (if not yet) */
983static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
984{
985 struct alc_spec *spec = codec->spec;
986 struct hda_input_mux *imux;
987 static char * const texts[3] = {
988 "Mic", "Internal Mic", "Dock Mic"
989 };
990 int i;
991
992 if (!spec->auto_mic)
993 return false;
994 imux = &spec->private_imux[0];
995 if (spec->input_mux == imux)
996 return true;
997 spec->imux_pins[0] = spec->ext_mic_pin;
998 spec->imux_pins[1] = spec->int_mic_pin;
999 spec->imux_pins[2] = spec->dock_mic_pin;
1000 for (i = 0; i < 3; i++) {
1001 strcpy(imux->items[i].label, texts[i]);
1002 if (spec->imux_pins[i])
1003 imux->num_items = i + 1;
1004 }
1005 spec->num_mux_defs = 1;
1006 spec->input_mux = imux;
1007 return true;
1008}
1009
1010/* check whether all auto-mic pins are valid; setup indices if OK */
1011static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1012{
1013 struct alc_spec *spec = codec->spec;
1014 const struct hda_input_mux *imux;
1015
1016 if (!spec->auto_mic)
1017 return false;
1018 if (spec->auto_mic_valid_imux)
1019 return true; /* already checked */
1020
1021 /* fill up imux indices */
1022 if (!alc_check_dyn_adc_switch(codec)) {
1023 spec->auto_mic = 0;
1024 return false;
1025 }
1026
1027 imux = spec->input_mux;
1028 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1029 spec->imux_pins, imux->num_items);
1030 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1031 spec->imux_pins, imux->num_items);
1032 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1033 spec->imux_pins, imux->num_items);
1034 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1035 spec->auto_mic = 0;
1036 return false; /* no corresponding imux */
1037 }
1038
1039 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1040 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001041 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001042 if (spec->dock_mic_pin)
1043 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1044 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001045 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001046
1047 spec->auto_mic_valid_imux = 1;
1048 spec->auto_mic = 1;
1049 return true;
1050}
1051
Takashi Iwai1d045db2011-07-07 18:23:21 +02001052/*
1053 * Check the availability of auto-mic switch;
1054 * Set up if really supported
1055 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001056static void alc_init_auto_mic(struct hda_codec *codec)
1057{
1058 struct alc_spec *spec = codec->spec;
1059 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001060 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001061 int i;
1062
Takashi Iwai21268962011-07-07 15:01:13 +02001063 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1064
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001065 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001066 for (i = 0; i < cfg->num_inputs; i++) {
1067 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001068 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001069 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001070 switch (snd_hda_get_input_pin_attr(defcfg)) {
1071 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001072 if (fixed)
1073 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001074 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1075 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001076 fixed = nid;
1077 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001078 case INPUT_PIN_ATTR_UNUSED:
1079 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001080 case INPUT_PIN_ATTR_DOCK:
1081 if (dock)
1082 return; /* already occupied */
1083 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1084 return; /* invalid type */
1085 dock = nid;
1086 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001087 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001088 if (ext)
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 ext = nid;
1093 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001094 }
1095 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001096 if (!ext && dock) {
1097 ext = dock;
1098 dock = 0;
1099 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001100 if (!ext || !fixed)
1101 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001102 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001103 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001104 if (dock && !is_jack_detectable(codec, dock))
1105 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001106
1107 /* check imux indices */
1108 spec->ext_mic_pin = ext;
1109 spec->int_mic_pin = fixed;
1110 spec->dock_mic_pin = dock;
1111
1112 spec->auto_mic = 1;
1113 if (!alc_auto_mic_check_imux(codec))
1114 return;
1115
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001116 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1117 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001118 spec->unsol_event = alc_sku_unsol_event;
1119}
1120
Takashi Iwai1d045db2011-07-07 18:23:21 +02001121/* check the availabilities of auto-mute and auto-mic switches */
1122static void alc_auto_check_switches(struct hda_codec *codec)
1123{
1124 alc_init_auto_hp(codec);
1125 alc_init_auto_mic(codec);
1126}
1127
1128/*
1129 * Realtek SSID verification
1130 */
1131
David Henningsson90622912010-10-14 14:50:18 +02001132/* Could be any non-zero and even value. When used as fixup, tells
1133 * the driver to ignore any present sku defines.
1134 */
1135#define ALC_FIXUP_SKU_IGNORE (2)
1136
Kailang Yangda00c242010-03-19 11:23:45 +01001137static int alc_auto_parse_customize_define(struct hda_codec *codec)
1138{
1139 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001140 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001141 struct alc_spec *spec = codec->spec;
1142
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001143 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1144
David Henningsson90622912010-10-14 14:50:18 +02001145 if (spec->cdefine.fixup) {
1146 ass = spec->cdefine.sku_cfg;
1147 if (ass == ALC_FIXUP_SKU_IGNORE)
1148 return -1;
1149 goto do_sku;
1150 }
1151
Kailang Yangda00c242010-03-19 11:23:45 +01001152 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001153 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001154 goto do_sku;
1155
1156 nid = 0x1d;
1157 if (codec->vendor_id == 0x10ec0260)
1158 nid = 0x17;
1159 ass = snd_hda_codec_get_pincfg(codec, nid);
1160
1161 if (!(ass & 1)) {
1162 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1163 codec->chip_name, ass);
1164 return -1;
1165 }
1166
1167 /* check sum */
1168 tmp = 0;
1169 for (i = 1; i < 16; i++) {
1170 if ((ass >> i) & 1)
1171 tmp++;
1172 }
1173 if (((ass >> 16) & 0xf) != tmp)
1174 return -1;
1175
1176 spec->cdefine.port_connectivity = ass >> 30;
1177 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1178 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1179 spec->cdefine.customization = ass >> 8;
1180do_sku:
1181 spec->cdefine.sku_cfg = ass;
1182 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1183 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1184 spec->cdefine.swap = (ass & 0x2) >> 1;
1185 spec->cdefine.override = ass & 0x1;
1186
1187 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1188 nid, spec->cdefine.sku_cfg);
1189 snd_printd("SKU: port_connectivity=0x%x\n",
1190 spec->cdefine.port_connectivity);
1191 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1192 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1193 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1194 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1195 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1196 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1197 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1198
1199 return 0;
1200}
1201
Takashi Iwai1d045db2011-07-07 18:23:21 +02001202/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001203static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1204{
Takashi Iwai21268962011-07-07 15:01:13 +02001205 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001206}
1207
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001208/* check subsystem ID and set up device-specific initialization;
1209 * return 1 if initialized, 0 if invalid SSID
1210 */
1211/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1212 * 31 ~ 16 : Manufacture ID
1213 * 15 ~ 8 : SKU ID
1214 * 7 ~ 0 : Assembly ID
1215 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1216 */
1217static int alc_subsystem_id(struct hda_codec *codec,
1218 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001219 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001220{
1221 unsigned int ass, tmp, i;
1222 unsigned nid;
1223 struct alc_spec *spec = codec->spec;
1224
David Henningsson90622912010-10-14 14:50:18 +02001225 if (spec->cdefine.fixup) {
1226 ass = spec->cdefine.sku_cfg;
1227 if (ass == ALC_FIXUP_SKU_IGNORE)
1228 return 0;
1229 goto do_sku;
1230 }
1231
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001232 ass = codec->subsystem_id & 0xffff;
1233 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1234 goto do_sku;
1235
1236 /* invalid SSID, check the special NID pin defcfg instead */
1237 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001238 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001239 * 29~21 : reserve
1240 * 20 : PCBEEP input
1241 * 19~16 : Check sum (15:1)
1242 * 15~1 : Custom
1243 * 0 : override
1244 */
1245 nid = 0x1d;
1246 if (codec->vendor_id == 0x10ec0260)
1247 nid = 0x17;
1248 ass = snd_hda_codec_get_pincfg(codec, nid);
1249 snd_printd("realtek: No valid SSID, "
1250 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001251 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001252 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001253 return 0;
1254 if ((ass >> 30) != 1) /* no physical connection */
1255 return 0;
1256
1257 /* check sum */
1258 tmp = 0;
1259 for (i = 1; i < 16; i++) {
1260 if ((ass >> i) & 1)
1261 tmp++;
1262 }
1263 if (((ass >> 16) & 0xf) != tmp)
1264 return 0;
1265do_sku:
1266 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1267 ass & 0xffff, codec->vendor_id);
1268 /*
1269 * 0 : override
1270 * 1 : Swap Jack
1271 * 2 : 0 --> Desktop, 1 --> Laptop
1272 * 3~5 : External Amplifier control
1273 * 7~6 : Reserved
1274 */
1275 tmp = (ass & 0x38) >> 3; /* external Amp control */
1276 switch (tmp) {
1277 case 1:
1278 spec->init_amp = ALC_INIT_GPIO1;
1279 break;
1280 case 3:
1281 spec->init_amp = ALC_INIT_GPIO2;
1282 break;
1283 case 7:
1284 spec->init_amp = ALC_INIT_GPIO3;
1285 break;
1286 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001287 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001288 spec->init_amp = ALC_INIT_DEFAULT;
1289 break;
1290 }
1291
1292 /* is laptop or Desktop and enable the function "Mute internal speaker
1293 * when the external headphone out jack is plugged"
1294 */
1295 if (!(ass & 0x8000))
1296 return 1;
1297 /*
1298 * 10~8 : Jack location
1299 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1300 * 14~13: Resvered
1301 * 15 : 1 --> enable the function "Mute internal speaker
1302 * when the external headphone out jack is plugged"
1303 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001304 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001305 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001306 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1307 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001308 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001309 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001310 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001311 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001312 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001313 else if (tmp == 3)
1314 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001315 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001316 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001317 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1318 spec->autocfg.line_outs))
1319 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001320 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001321 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001322 return 1;
1323}
Kailang Yangea1fb292008-08-26 12:58:38 +02001324
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001325static void alc_ssid_check(struct hda_codec *codec,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001326 hda_nid_t porta, hda_nid_t porte,
1327 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001328{
Kailang Yang6227cdc2010-02-25 08:36:52 +01001329 if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001330 struct alc_spec *spec = codec->spec;
1331 snd_printd("realtek: "
1332 "Enable default setup for auto mode as fallback\n");
1333 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001334 }
Takashi Iwai21268962011-07-07 15:01:13 +02001335}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001336
Takashi Iwai41e41f12005-06-08 14:48:49 +02001337/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001338 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001339 */
1340
1341struct alc_pincfg {
1342 hda_nid_t nid;
1343 u32 val;
1344};
1345
Todd Broche1eb5f12010-12-06 11:19:51 -08001346struct alc_model_fixup {
1347 const int id;
1348 const char *name;
1349};
1350
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001351struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001352 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001353 bool chained;
1354 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001355 union {
1356 unsigned int sku;
1357 const struct alc_pincfg *pins;
1358 const struct hda_verb *verbs;
1359 void (*func)(struct hda_codec *codec,
1360 const struct alc_fixup *fix,
1361 int action);
1362 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001363};
1364
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001365enum {
1366 ALC_FIXUP_INVALID,
1367 ALC_FIXUP_SKU,
1368 ALC_FIXUP_PINS,
1369 ALC_FIXUP_VERBS,
1370 ALC_FIXUP_FUNC,
1371};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001372
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001373enum {
1374 ALC_FIXUP_ACT_PRE_PROBE,
1375 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001376 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001377};
1378
1379static void alc_apply_fixup(struct hda_codec *codec, int action)
1380{
1381 struct alc_spec *spec = codec->spec;
1382 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001383#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001384 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001385#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001386 int depth = 0;
1387
1388 if (!spec->fixup_list)
1389 return;
1390
1391 while (id >= 0) {
1392 const struct alc_fixup *fix = spec->fixup_list + id;
1393 const struct alc_pincfg *cfg;
1394
1395 switch (fix->type) {
1396 case ALC_FIXUP_SKU:
1397 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1398 break;;
1399 snd_printdd(KERN_INFO "hda_codec: %s: "
1400 "Apply sku override for %s\n",
1401 codec->chip_name, modelname);
1402 spec->cdefine.sku_cfg = fix->v.sku;
1403 spec->cdefine.fixup = 1;
1404 break;
1405 case ALC_FIXUP_PINS:
1406 cfg = fix->v.pins;
1407 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1408 break;
1409 snd_printdd(KERN_INFO "hda_codec: %s: "
1410 "Apply pincfg for %s\n",
1411 codec->chip_name, modelname);
1412 for (; cfg->nid; cfg++)
1413 snd_hda_codec_set_pincfg(codec, cfg->nid,
1414 cfg->val);
1415 break;
1416 case ALC_FIXUP_VERBS:
1417 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1418 break;
1419 snd_printdd(KERN_INFO "hda_codec: %s: "
1420 "Apply fix-verbs for %s\n",
1421 codec->chip_name, modelname);
1422 add_verb(codec->spec, fix->v.verbs);
1423 break;
1424 case ALC_FIXUP_FUNC:
1425 if (!fix->v.func)
1426 break;
1427 snd_printdd(KERN_INFO "hda_codec: %s: "
1428 "Apply fix-func for %s\n",
1429 codec->chip_name, modelname);
1430 fix->v.func(codec, fix, action);
1431 break;
1432 default:
1433 snd_printk(KERN_ERR "hda_codec: %s: "
1434 "Invalid fixup type %d\n",
1435 codec->chip_name, fix->type);
1436 break;
1437 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001438 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001439 break;
1440 if (++depth > 10)
1441 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001442 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001443 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001444}
1445
Todd Broche1eb5f12010-12-06 11:19:51 -08001446static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001447 const struct alc_model_fixup *models,
1448 const struct snd_pci_quirk *quirk,
1449 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001450{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001451 struct alc_spec *spec = codec->spec;
1452 int id = -1;
1453 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001454
Todd Broche1eb5f12010-12-06 11:19:51 -08001455 if (codec->modelname && models) {
1456 while (models->name) {
1457 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001458 id = models->id;
1459 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001460 break;
1461 }
1462 models++;
1463 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001464 }
1465 if (id < 0) {
1466 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1467 if (quirk) {
1468 id = quirk->value;
1469#ifdef CONFIG_SND_DEBUG_VERBOSE
1470 name = quirk->name;
1471#endif
1472 }
1473 }
1474
1475 spec->fixup_id = id;
1476 if (id >= 0) {
1477 spec->fixup_list = fixlist;
1478 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001479 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001480}
1481
Takashi Iwai1d045db2011-07-07 18:23:21 +02001482/*
1483 * COEF access helper functions
1484 */
Kailang Yang274693f2009-12-03 10:07:50 +01001485static int alc_read_coef_idx(struct hda_codec *codec,
1486 unsigned int coef_idx)
1487{
1488 unsigned int val;
1489 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1490 coef_idx);
1491 val = snd_hda_codec_read(codec, 0x20, 0,
1492 AC_VERB_GET_PROC_COEF, 0);
1493 return val;
1494}
1495
Kailang Yang977ddd62010-09-15 10:02:29 +02001496static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1497 unsigned int coef_val)
1498{
1499 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1500 coef_idx);
1501 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1502 coef_val);
1503}
1504
Takashi Iwai1d045db2011-07-07 18:23:21 +02001505/*
1506 * Digital I/O handling
1507 */
1508
Takashi Iwai757899a2010-07-30 10:48:14 +02001509/* set right pin controls for digital I/O */
1510static void alc_auto_init_digital(struct hda_codec *codec)
1511{
1512 struct alc_spec *spec = codec->spec;
1513 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001514 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001515
1516 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1517 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001518 if (!pin)
1519 continue;
1520 snd_hda_codec_write(codec, pin, 0,
1521 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1522 if (!i)
1523 dac = spec->multiout.dig_out_nid;
1524 else
1525 dac = spec->slave_dig_outs[i - 1];
1526 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1527 continue;
1528 snd_hda_codec_write(codec, dac, 0,
1529 AC_VERB_SET_AMP_GAIN_MUTE,
1530 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001531 }
1532 pin = spec->autocfg.dig_in_pin;
1533 if (pin)
1534 snd_hda_codec_write(codec, pin, 0,
1535 AC_VERB_SET_PIN_WIDGET_CONTROL,
1536 PIN_IN);
1537}
1538
1539/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1540static void alc_auto_parse_digital(struct hda_codec *codec)
1541{
1542 struct alc_spec *spec = codec->spec;
1543 int i, err;
1544 hda_nid_t dig_nid;
1545
1546 /* support multiple SPDIFs; the secondary is set up as a slave */
1547 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001548 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001549 err = snd_hda_get_connections(codec,
1550 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001551 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001552 if (err < 0)
1553 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001554 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001555 if (!i) {
1556 spec->multiout.dig_out_nid = dig_nid;
1557 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1558 } else {
1559 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1560 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1561 break;
1562 spec->slave_dig_outs[i - 1] = dig_nid;
1563 }
1564 }
1565
1566 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001567 dig_nid = codec->start_nid;
1568 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1569 unsigned int wcaps = get_wcaps(codec, dig_nid);
1570 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1571 continue;
1572 if (!(wcaps & AC_WCAP_DIGITAL))
1573 continue;
1574 if (!(wcaps & AC_WCAP_CONN_LIST))
1575 continue;
1576 err = get_connection_index(codec, dig_nid,
1577 spec->autocfg.dig_in_pin);
1578 if (err >= 0) {
1579 spec->dig_in_nid = dig_nid;
1580 break;
1581 }
1582 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001583 }
1584}
1585
Takashi Iwaif95474e2007-07-10 00:47:43 +02001586/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001587 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001588 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001589static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1590 struct snd_ctl_elem_info *uinfo)
1591{
1592 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1593 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001594 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001595 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001596
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001597 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001598 if (spec->vol_in_capsrc)
1599 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1600 else
1601 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1602 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001603 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001604 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001605 return err;
1606}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001608static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1609 unsigned int size, unsigned int __user *tlv)
1610{
1611 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1612 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001613 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001614 int err;
1615
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001616 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001617 if (spec->vol_in_capsrc)
1618 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1619 else
1620 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1621 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001622 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001623 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001624 return err;
1625}
1626
1627typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1628 struct snd_ctl_elem_value *ucontrol);
1629
1630static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1631 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001632 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001633{
1634 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1635 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001636 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001637
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001638 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001639 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001640 for (i = 0; i < spec->num_adc_nids; i++) {
1641 kcontrol->private_value =
1642 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1643 3, 0, HDA_INPUT);
1644 err = func(kcontrol, ucontrol);
1645 if (err < 0)
1646 goto error;
1647 }
1648 } else {
1649 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001650 if (spec->vol_in_capsrc)
1651 kcontrol->private_value =
1652 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1653 3, 0, HDA_OUTPUT);
1654 else
1655 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001656 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1657 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001658 err = func(kcontrol, ucontrol);
1659 }
1660 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001661 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001662 return err;
1663}
1664
1665static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1666 struct snd_ctl_elem_value *ucontrol)
1667{
1668 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001669 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001670}
1671
1672static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1673 struct snd_ctl_elem_value *ucontrol)
1674{
1675 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001676 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001677}
1678
1679/* capture mixer elements */
1680#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1681
1682static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1683 struct snd_ctl_elem_value *ucontrol)
1684{
1685 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001686 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001687}
1688
1689static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1690 struct snd_ctl_elem_value *ucontrol)
1691{
1692 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001693 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001694}
1695
Takashi Iwaia23b6882009-03-23 15:21:36 +01001696#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001697 { \
1698 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1699 .name = "Capture Switch", \
1700 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1701 .count = num, \
1702 .info = alc_cap_sw_info, \
1703 .get = alc_cap_sw_get, \
1704 .put = alc_cap_sw_put, \
1705 }, \
1706 { \
1707 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1708 .name = "Capture Volume", \
1709 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1710 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1711 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1712 .count = num, \
1713 .info = alc_cap_vol_info, \
1714 .get = alc_cap_vol_get, \
1715 .put = alc_cap_vol_put, \
1716 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001717 }
1718
1719#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001720 { \
1721 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1722 /* .name = "Capture Source", */ \
1723 .name = "Input Source", \
1724 .count = num, \
1725 .info = alc_mux_enum_info, \
1726 .get = alc_mux_enum_get, \
1727 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001728 }
1729
1730#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001731static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001732 _DEFINE_CAPMIX(num), \
1733 _DEFINE_CAPSRC(num), \
1734 { } /* end */ \
1735}
1736
1737#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001738static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001739 _DEFINE_CAPMIX(num), \
1740 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001741}
1742
1743/* up to three ADCs */
1744DEFINE_CAPMIX(1);
1745DEFINE_CAPMIX(2);
1746DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001747DEFINE_CAPMIX_NOSRC(1);
1748DEFINE_CAPMIX_NOSRC(2);
1749DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001750
1751/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001752 * virtual master controls
1753 */
1754
1755/*
1756 * slave controls for virtual master
1757 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001758static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001759 "Front Playback Volume",
1760 "Surround Playback Volume",
1761 "Center Playback Volume",
1762 "LFE Playback Volume",
1763 "Side Playback Volume",
1764 "Headphone Playback Volume",
1765 "Speaker Playback Volume",
1766 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001767 "Line-Out Playback Volume",
1768 NULL,
1769};
1770
Takashi Iwaiea734962011-01-17 11:29:34 +01001771static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001772 "Front Playback Switch",
1773 "Surround Playback Switch",
1774 "Center Playback Switch",
1775 "LFE Playback Switch",
1776 "Side Playback Switch",
1777 "Headphone Playback Switch",
1778 "Speaker Playback Switch",
1779 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001780 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001781 "Line-Out Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001782 NULL,
1783};
1784
1785/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001786 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001788
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001789#define NID_MAPPING (-1)
1790
1791#define SUBDEV_SPEAKER_ (0 << 6)
1792#define SUBDEV_HP_ (1 << 6)
1793#define SUBDEV_LINE_ (2 << 6)
1794#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1795#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1796#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1797
Takashi Iwai603c4012008-07-30 15:01:44 +02001798static void alc_free_kctls(struct hda_codec *codec);
1799
Takashi Iwai67d634c2009-11-16 15:35:59 +01001800#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001801/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001802static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001803 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001804 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001805 { } /* end */
1806};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001807#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001808
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809static int alc_build_controls(struct hda_codec *codec)
1810{
1811 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001812 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001813 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001814 int i, j, err;
1815 unsigned int u;
1816 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
1818 for (i = 0; i < spec->num_mixers; i++) {
1819 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1820 if (err < 0)
1821 return err;
1822 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001823 if (spec->cap_mixer) {
1824 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1825 if (err < 0)
1826 return err;
1827 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001829 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001830 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001831 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 if (err < 0)
1833 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001834 if (!spec->no_analog) {
1835 err = snd_hda_create_spdif_share_sw(codec,
1836 &spec->multiout);
1837 if (err < 0)
1838 return err;
1839 spec->multiout.share_spdif = 1;
1840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 }
1842 if (spec->dig_in_nid) {
1843 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1844 if (err < 0)
1845 return err;
1846 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001847
Takashi Iwai67d634c2009-11-16 15:35:59 +01001848#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001849 /* create beep controls if needed */
1850 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001851 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001852 for (knew = alc_beep_mixer; knew->name; knew++) {
1853 struct snd_kcontrol *kctl;
1854 kctl = snd_ctl_new1(knew, codec);
1855 if (!kctl)
1856 return -ENOMEM;
1857 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001858 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001859 if (err < 0)
1860 return err;
1861 }
1862 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001863#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001864
Takashi Iwai2134ea42008-01-10 16:53:55 +01001865 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001866 if (!spec->no_analog &&
1867 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001868 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001869 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001870 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001871 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001872 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001873 if (err < 0)
1874 return err;
1875 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001876 if (!spec->no_analog &&
1877 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001878 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1879 NULL, alc_slave_sws);
1880 if (err < 0)
1881 return err;
1882 }
1883
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001884 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001885 if (spec->capsrc_nids || spec->adc_nids) {
1886 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1887 if (!kctl)
1888 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1889 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001890 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001891 if (!nids)
1892 nids = spec->adc_nids;
1893 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1894 if (err < 0)
1895 return err;
1896 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001897 }
1898 if (spec->cap_mixer) {
1899 const char *kname = kctl ? kctl->id.name : NULL;
1900 for (knew = spec->cap_mixer; knew->name; knew++) {
1901 if (kname && strcmp(knew->name, kname) == 0)
1902 continue;
1903 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1904 for (i = 0; kctl && i < kctl->count; i++) {
1905 err = snd_hda_add_nid(codec, kctl, i,
1906 spec->adc_nids[i]);
1907 if (err < 0)
1908 return err;
1909 }
1910 }
1911 }
1912
1913 /* other nid->control mapping */
1914 for (i = 0; i < spec->num_mixers; i++) {
1915 for (knew = spec->mixers[i]; knew->name; knew++) {
1916 if (knew->iface != NID_MAPPING)
1917 continue;
1918 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1919 if (kctl == NULL)
1920 continue;
1921 u = knew->subdevice;
1922 for (j = 0; j < 4; j++, u >>= 8) {
1923 nid = u & 0x3f;
1924 if (nid == 0)
1925 continue;
1926 switch (u & 0xc0) {
1927 case SUBDEV_SPEAKER_:
1928 nid = spec->autocfg.speaker_pins[nid];
1929 break;
1930 case SUBDEV_LINE_:
1931 nid = spec->autocfg.line_out_pins[nid];
1932 break;
1933 case SUBDEV_HP_:
1934 nid = spec->autocfg.hp_pins[nid];
1935 break;
1936 default:
1937 continue;
1938 }
1939 err = snd_hda_add_nid(codec, kctl, 0, nid);
1940 if (err < 0)
1941 return err;
1942 }
1943 u = knew->private_value;
1944 for (j = 0; j < 4; j++, u >>= 8) {
1945 nid = u & 0xff;
1946 if (nid == 0)
1947 continue;
1948 err = snd_hda_add_nid(codec, kctl, 0, nid);
1949 if (err < 0)
1950 return err;
1951 }
1952 }
1953 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001954
1955 alc_free_kctls(codec); /* no longer needed */
1956
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 return 0;
1958}
1959
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001960
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001962 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001963 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001964
Takashi Iwai584c0c42011-03-10 12:51:11 +01001965static void alc_init_special_input_src(struct hda_codec *codec);
1966
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967static int alc_init(struct hda_codec *codec)
1968{
1969 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001970 unsigned int i;
1971
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001972 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001973 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001974
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001975 for (i = 0; i < spec->num_init_verbs; i++)
1976 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01001977 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001978
1979 if (spec->init_hook)
1980 spec->init_hook(codec);
1981
Takashi Iwai58701122011-01-13 15:41:45 +01001982 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
1983
Takashi Iwai9e5341b2010-09-21 09:57:06 +02001984 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 return 0;
1986}
1987
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001988static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
1989{
1990 struct alc_spec *spec = codec->spec;
1991
1992 if (spec->unsol_event)
1993 spec->unsol_event(codec, res);
1994}
1995
Takashi Iwaicb53c622007-08-10 17:21:45 +02001996#ifdef CONFIG_SND_HDA_POWER_SAVE
1997static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
1998{
1999 struct alc_spec *spec = codec->spec;
2000 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2001}
2002#endif
2003
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004/*
2005 * Analog playback callbacks
2006 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002007static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002009 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010{
2011 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002012 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2013 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014}
2015
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002016static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 struct hda_codec *codec,
2018 unsigned int stream_tag,
2019 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002020 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021{
2022 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002023 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2024 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025}
2026
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002027static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002029 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030{
2031 struct alc_spec *spec = codec->spec;
2032 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2033}
2034
2035/*
2036 * Digital out
2037 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002038static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002040 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041{
2042 struct alc_spec *spec = codec->spec;
2043 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2044}
2045
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002046static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002047 struct hda_codec *codec,
2048 unsigned int stream_tag,
2049 unsigned int format,
2050 struct snd_pcm_substream *substream)
2051{
2052 struct alc_spec *spec = codec->spec;
2053 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2054 stream_tag, format, substream);
2055}
2056
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002057static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002058 struct hda_codec *codec,
2059 struct snd_pcm_substream *substream)
2060{
2061 struct alc_spec *spec = codec->spec;
2062 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2063}
2064
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002065static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002067 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068{
2069 struct alc_spec *spec = codec->spec;
2070 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2071}
2072
2073/*
2074 * Analog capture
2075 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002076static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 struct hda_codec *codec,
2078 unsigned int stream_tag,
2079 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002080 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081{
2082 struct alc_spec *spec = codec->spec;
2083
Takashi Iwai63300792008-01-24 15:31:36 +01002084 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 stream_tag, 0, format);
2086 return 0;
2087}
2088
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002089static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002091 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092{
2093 struct alc_spec *spec = codec->spec;
2094
Takashi Iwai888afa12008-03-18 09:57:50 +01002095 snd_hda_codec_cleanup_stream(codec,
2096 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 return 0;
2098}
2099
Takashi Iwai840b64c2010-07-13 22:49:01 +02002100/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002101static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002102 struct hda_codec *codec,
2103 unsigned int stream_tag,
2104 unsigned int format,
2105 struct snd_pcm_substream *substream)
2106{
2107 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002108 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002109 spec->cur_adc_stream_tag = stream_tag;
2110 spec->cur_adc_format = format;
2111 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2112 return 0;
2113}
2114
Takashi Iwai21268962011-07-07 15:01:13 +02002115static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002116 struct hda_codec *codec,
2117 struct snd_pcm_substream *substream)
2118{
2119 struct alc_spec *spec = codec->spec;
2120 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2121 spec->cur_adc = 0;
2122 return 0;
2123}
2124
Takashi Iwai21268962011-07-07 15:01:13 +02002125static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002126 .substreams = 1,
2127 .channels_min = 2,
2128 .channels_max = 2,
2129 .nid = 0, /* fill later */
2130 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002131 .prepare = dyn_adc_capture_pcm_prepare,
2132 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002133 },
2134};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135
2136/*
2137 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002138static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 .substreams = 1,
2140 .channels_min = 2,
2141 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002142 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002144 .open = alc_playback_pcm_open,
2145 .prepare = alc_playback_pcm_prepare,
2146 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 },
2148};
2149
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002150static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002151 .substreams = 1,
2152 .channels_min = 2,
2153 .channels_max = 2,
2154 /* NID is set in alc_build_pcms */
2155};
2156
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002157static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002158 .substreams = 1,
2159 .channels_min = 2,
2160 .channels_max = 2,
2161 /* NID is set in alc_build_pcms */
2162};
2163
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002164static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002165 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 .channels_min = 2,
2167 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002168 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002170 .prepare = alc_alt_capture_pcm_prepare,
2171 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 },
2173};
2174
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002175static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 .substreams = 1,
2177 .channels_min = 2,
2178 .channels_max = 2,
2179 /* NID is set in alc_build_pcms */
2180 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002181 .open = alc_dig_playback_pcm_open,
2182 .close = alc_dig_playback_pcm_close,
2183 .prepare = alc_dig_playback_pcm_prepare,
2184 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 },
2186};
2187
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002188static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 .substreams = 1,
2190 .channels_min = 2,
2191 .channels_max = 2,
2192 /* NID is set in alc_build_pcms */
2193};
2194
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002195/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002196static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002197 .substreams = 0,
2198 .channels_min = 0,
2199 .channels_max = 0,
2200};
2201
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202static int alc_build_pcms(struct hda_codec *codec)
2203{
2204 struct alc_spec *spec = codec->spec;
2205 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002206 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 int i;
2208
2209 codec->num_pcms = 1;
2210 codec->pcm_info = info;
2211
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002212 if (spec->no_analog)
2213 goto skip_analog;
2214
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002215 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2216 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002218
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002219 if (spec->multiout.dac_nids > 0) {
2220 p = spec->stream_analog_playback;
2221 if (!p)
2222 p = &alc_pcm_analog_playback;
2223 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002224 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2225 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002226 if (spec->adc_nids) {
2227 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002228 if (!p) {
2229 if (spec->dyn_adc_switch)
2230 p = &dyn_adc_pcm_analog_capture;
2231 else
2232 p = &alc_pcm_analog_capture;
2233 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002234 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002235 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
Takashi Iwai4a471b72005-12-07 13:56:29 +01002238 if (spec->channel_mode) {
2239 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2240 for (i = 0; i < spec->num_channel_mode; i++) {
2241 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2242 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 }
2245 }
2246
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002247 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002248 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002250 snprintf(spec->stream_name_digital,
2251 sizeof(spec->stream_name_digital),
2252 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002253 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002254 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002255 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002257 if (spec->dig_out_type)
2258 info->pcm_type = spec->dig_out_type;
2259 else
2260 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002261 if (spec->multiout.dig_out_nid) {
2262 p = spec->stream_digital_playback;
2263 if (!p)
2264 p = &alc_pcm_digital_playback;
2265 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2267 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002268 if (spec->dig_in_nid) {
2269 p = spec->stream_digital_capture;
2270 if (!p)
2271 p = &alc_pcm_digital_capture;
2272 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2274 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002275 /* FIXME: do we need this for all Realtek codec models? */
2276 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 }
2278
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002279 if (spec->no_analog)
2280 return 0;
2281
Takashi Iwaie08a0072006-09-07 17:52:14 +02002282 /* If the use of more than one ADC is requested for the current
2283 * model, configure a second analog capture-only PCM.
2284 */
2285 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002286 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002287 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002288 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002289 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002290 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002291 p = spec->stream_analog_alt_playback;
2292 if (!p)
2293 p = &alc_pcm_analog_alt_playback;
2294 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002295 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2296 spec->alt_dac_nid;
2297 } else {
2298 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2299 alc_pcm_null_stream;
2300 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2301 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002302 if (spec->num_adc_nids > 1) {
2303 p = spec->stream_analog_alt_capture;
2304 if (!p)
2305 p = &alc_pcm_analog_alt_capture;
2306 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002307 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2308 spec->adc_nids[1];
2309 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2310 spec->num_adc_nids - 1;
2311 } else {
2312 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2313 alc_pcm_null_stream;
2314 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002315 }
2316 }
2317
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 return 0;
2319}
2320
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002321static inline void alc_shutup(struct hda_codec *codec)
2322{
Takashi Iwai1c716152011-04-07 10:37:16 +02002323 struct alc_spec *spec = codec->spec;
2324
2325 if (spec && spec->shutup)
2326 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002327 snd_hda_shutup_pins(codec);
2328}
2329
Takashi Iwai603c4012008-07-30 15:01:44 +02002330static void alc_free_kctls(struct hda_codec *codec)
2331{
2332 struct alc_spec *spec = codec->spec;
2333
2334 if (spec->kctls.list) {
2335 struct snd_kcontrol_new *kctl = spec->kctls.list;
2336 int i;
2337 for (i = 0; i < spec->kctls.used; i++)
2338 kfree(kctl[i].name);
2339 }
2340 snd_array_free(&spec->kctls);
2341}
2342
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343static void alc_free(struct hda_codec *codec)
2344{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002345 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002346
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002347 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002348 return;
2349
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002350 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002351 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002352 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002353 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002354 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355}
2356
Hector Martinf5de24b2009-12-20 22:51:31 +01002357#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002358static void alc_power_eapd(struct hda_codec *codec)
2359{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002360 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002361}
2362
Hector Martinf5de24b2009-12-20 22:51:31 +01002363static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2364{
2365 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002366 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002367 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002368 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002369 return 0;
2370}
2371#endif
2372
Takashi Iwaie044c392008-10-27 16:56:24 +01002373#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaie044c392008-10-27 16:56:24 +01002374static int alc_resume(struct hda_codec *codec)
2375{
Takashi Iwai1c716152011-04-07 10:37:16 +02002376 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002377 codec->patch_ops.init(codec);
2378 snd_hda_codec_resume_amp(codec);
2379 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002380 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002381 return 0;
2382}
Takashi Iwaie044c392008-10-27 16:56:24 +01002383#endif
2384
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385/*
2386 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002387static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 .build_controls = alc_build_controls,
2389 .build_pcms = alc_build_pcms,
2390 .init = alc_init,
2391 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002392 .unsol_event = alc_unsol_event,
Takashi Iwaie044c392008-10-27 16:56:24 +01002393#ifdef SND_HDA_NEEDS_RESUME
2394 .resume = alc_resume,
2395#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002396#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002397 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002398 .check_power_status = alc_check_power_status,
2399#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002400 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401};
2402
Kailang Yangc027ddc2010-03-19 11:33:06 +01002403/* replace the codec chip_name with the given string */
2404static int alc_codec_rename(struct hda_codec *codec, const char *name)
2405{
2406 kfree(codec->chip_name);
2407 codec->chip_name = kstrdup(name, GFP_KERNEL);
2408 if (!codec->chip_name) {
2409 alc_free(codec);
2410 return -ENOMEM;
2411 }
2412 return 0;
2413}
2414
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002415/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002416 * Automatic parse of I/O pins from the BIOS configuration
2417 */
2418
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002419enum {
2420 ALC_CTL_WIDGET_VOL,
2421 ALC_CTL_WIDGET_MUTE,
2422 ALC_CTL_BIND_MUTE,
2423};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002424static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002425 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2426 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002427 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002428};
2429
2430/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002431static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002432 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002433{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002434 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002435
Takashi Iwaice764ab2011-04-27 16:35:23 +02002436 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002437 if (!knew)
2438 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002439 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002440 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002441 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002442 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002443 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002444 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002445 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002446 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002447 return 0;
2448}
2449
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002450static int add_control_with_pfx(struct alc_spec *spec, int type,
2451 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002452 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002453{
2454 char name[32];
2455 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002456 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002457}
2458
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002459#define add_pb_vol_ctrl(spec, type, pfx, val) \
2460 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2461#define add_pb_sw_ctrl(spec, type, pfx, val) \
2462 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2463#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2464 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2465#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2466 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002467
Takashi Iwai6843ca12011-06-24 11:03:58 +02002468static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2469 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002470{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002471 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002472 static const char * const chname[4] = {
2473 "Front", "Surround", NULL /*CLFE*/, "Side"
2474 };
Takashi Iwaice764ab2011-04-27 16:35:23 +02002475
Takashi Iwai6843ca12011-06-24 11:03:58 +02002476 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002477 if (cfg->line_outs == 1 && !spec->multi_ios &&
2478 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002479 return "Master";
2480
2481 switch (cfg->line_out_type) {
2482 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002483 if (cfg->line_outs == 1)
2484 return "Speaker";
2485 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002486 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002487 /* for multi-io case, only the primary out */
2488 if (ch && spec->multi_ios)
2489 break;
2490 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002491 return "Headphone";
2492 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002493 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002494 return "PCM";
2495 break;
2496 }
Takashi Iwai6843ca12011-06-24 11:03:58 +02002497 return chname[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002498}
2499
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002500/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002501static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002502 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002503 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002504{
Kailang Yangdf694da2005-12-05 19:42:22 +01002505 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002506
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002507 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002508 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2509 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002510 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002511 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002512 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2513 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002514 return err;
2515 return 0;
2516}
2517
Takashi Iwai05f5f472009-08-25 13:10:18 +02002518static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002519{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002520 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2521 return (pincap & AC_PINCAP_IN) != 0;
2522}
2523
Takashi Iwai1d045db2011-07-07 18:23:21 +02002524/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002525static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002526{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002527 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002528 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002529 hda_nid_t *adc_nids = spec->private_adc_nids;
2530 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2531 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2532 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002533 int i, nums = 0;
2534
2535 nid = codec->start_nid;
2536 for (i = 0; i < codec->num_nodes; i++, nid++) {
2537 hda_nid_t src;
2538 const hda_nid_t *list;
2539 unsigned int caps = get_wcaps(codec, nid);
2540 int type = get_wcaps_type(caps);
2541
2542 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2543 continue;
2544 adc_nids[nums] = nid;
2545 cap_nids[nums] = nid;
2546 src = nid;
2547 for (;;) {
2548 int n;
2549 type = get_wcaps_type(get_wcaps(codec, src));
2550 if (type == AC_WID_PIN)
2551 break;
2552 if (type == AC_WID_AUD_SEL) {
2553 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002554 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002555 break;
2556 }
2557 n = snd_hda_get_conn_list(codec, src, &list);
2558 if (n > 1) {
2559 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002560 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002561 break;
2562 } else if (n != 1)
2563 break;
2564 src = *list;
2565 }
2566 if (++nums >= max_nums)
2567 break;
2568 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002569 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002570 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002571 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002572 return nums;
2573}
2574
Takashi Iwai05f5f472009-08-25 13:10:18 +02002575/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002576static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002577{
2578 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002579 const struct auto_pin_cfg *cfg = &spec->autocfg;
2580 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002581 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002582 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002583 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002584 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002585
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002586 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002587 if (num_adcs < 0)
2588 return 0;
2589
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002590 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002591 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002592 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002593
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002594 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002595 if (!alc_is_input_pin(codec, pin))
2596 continue;
2597
David Henningsson5322bf22011-01-05 11:03:56 +01002598 label = hda_get_autocfg_input_label(codec, cfg, i);
2599 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002600 type_idx++;
2601 else
2602 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002603 prev_label = label;
2604
Takashi Iwai05f5f472009-08-25 13:10:18 +02002605 if (mixer) {
2606 idx = get_connection_index(codec, mixer, pin);
2607 if (idx >= 0) {
2608 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002609 label, type_idx,
2610 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002611 if (err < 0)
2612 return err;
2613 }
2614 }
2615
Takashi Iwaib7821702011-07-06 15:12:46 +02002616 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002617 hda_nid_t cap = spec->capsrc_nids ?
2618 spec->capsrc_nids[c] : spec->adc_nids[c];
2619 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002620 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002621 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002622 snd_hda_add_imux_item(imux, label, idx, NULL);
2623 break;
2624 }
2625 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002626 }
Takashi Iwai21268962011-07-07 15:01:13 +02002627
2628 spec->num_mux_defs = 1;
2629 spec->input_mux = imux;
2630
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002631 return 0;
2632}
2633
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002634static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2635 unsigned int pin_type)
2636{
2637 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2638 pin_type);
2639 /* unmute pin */
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002640 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2641 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002642}
2643
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002644static int get_pin_type(int line_out_type)
2645{
2646 if (line_out_type == AUTO_PIN_HP_OUT)
2647 return PIN_HP;
2648 else
2649 return PIN_OUT;
2650}
2651
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002652static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002653{
2654 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002655 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002656 int i;
2657
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002658 for (i = 0; i < cfg->num_inputs; i++) {
2659 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002660 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002661 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002662 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002663 snd_hda_codec_write(codec, nid, 0,
2664 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002665 AMP_OUT_MUTE);
2666 }
2667 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002668
2669 /* mute all loopback inputs */
2670 if (spec->mixer_nid) {
2671 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2672 for (i = 0; i < nums; i++)
2673 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2674 AC_VERB_SET_AMP_GAIN_MUTE,
2675 AMP_IN_MUTE(i));
2676 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002677}
2678
Takashi Iwai7085ec12009-10-02 09:03:58 +02002679/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002680static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002681{
Takashi Iwai604401a2011-04-27 15:14:23 +02002682 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002683 int i, num;
2684
2685 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2686 for (i = 0; i < num; i++) {
2687 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2688 return list[i];
2689 }
2690 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002691}
2692
Takashi Iwai604401a2011-04-27 15:14:23 +02002693/* go down to the selector widget before the mixer */
2694static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2695{
2696 hda_nid_t srcs[5];
2697 int num = snd_hda_get_connections(codec, pin, srcs,
2698 ARRAY_SIZE(srcs));
2699 if (num != 1 ||
2700 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2701 return pin;
2702 return srcs[0];
2703}
2704
Takashi Iwai7085ec12009-10-02 09:03:58 +02002705/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002706static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002707 hda_nid_t dac)
2708{
David Henningssoncc1c4522010-11-24 14:17:47 +01002709 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002710 int i, num;
2711
Takashi Iwai604401a2011-04-27 15:14:23 +02002712 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002713 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2714 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002715 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002716 return mix[i];
2717 }
2718 return 0;
2719}
2720
Takashi Iwaice764ab2011-04-27 16:35:23 +02002721/* select the connection from pin to DAC if needed */
2722static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2723 hda_nid_t dac)
2724{
2725 hda_nid_t mix[5];
2726 int i, num;
2727
2728 pin = alc_go_down_to_selector(codec, pin);
2729 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2730 if (num < 2)
2731 return 0;
2732 for (i = 0; i < num; i++) {
2733 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2734 snd_hda_codec_update_cache(codec, pin, 0,
2735 AC_VERB_SET_CONNECT_SEL, i);
2736 return 0;
2737 }
2738 }
2739 return 0;
2740}
2741
Takashi Iwai7085ec12009-10-02 09:03:58 +02002742/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002743static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002744{
2745 struct alc_spec *spec = codec->spec;
2746 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002747 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002748
Takashi Iwai604401a2011-04-27 15:14:23 +02002749 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002750 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002751 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002752 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002753 if (!nid)
2754 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002755 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2756 spec->multiout.num_dacs))
2757 continue;
2758 if (spec->multiout.hp_nid == nid)
2759 continue;
2760 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2761 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2762 continue;
2763 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002764 }
2765 return 0;
2766}
2767
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002768static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2769{
2770 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2771 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2772 return alc_auto_look_for_dac(codec, pin);
2773 return 0;
2774}
2775
Takashi Iwai7085ec12009-10-02 09:03:58 +02002776/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002777static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002778{
2779 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002780 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002781 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002782 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002783
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002784 again:
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02002785 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002786 spec->multiout.hp_nid = 0;
2787 spec->multiout.extra_out_nid[0] = 0;
2788 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2789 spec->multiout.dac_nids = spec->private_dac_nids;
2790
2791 /* fill hard-wired DACs first */
2792 if (!redone) {
2793 for (i = 0; i < cfg->line_outs; i++)
2794 spec->private_dac_nids[i] =
2795 get_dac_if_single(codec, cfg->line_out_pins[i]);
2796 if (cfg->hp_outs)
2797 spec->multiout.hp_nid =
2798 get_dac_if_single(codec, cfg->hp_pins[0]);
2799 if (cfg->speaker_outs)
2800 spec->multiout.extra_out_nid[0] =
2801 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002802 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002803
2804 for (i = 0; i < cfg->line_outs; i++) {
2805 hda_nid_t pin = cfg->line_out_pins[i];
2806 if (spec->private_dac_nids[i])
2807 continue;
2808 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2809 if (!spec->private_dac_nids[i] && !redone) {
2810 /* if we can't find primary DACs, re-probe without
2811 * checking the hard-wired DACs
2812 */
2813 redone = true;
2814 goto again;
2815 }
2816 }
2817
2818 for (i = 0; i < cfg->line_outs; i++) {
2819 if (spec->private_dac_nids[i])
2820 spec->multiout.num_dacs++;
2821 else
2822 memmove(spec->private_dac_nids + i,
2823 spec->private_dac_nids + i + 1,
2824 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2825 }
2826
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002827 if (cfg->hp_outs && !spec->multiout.hp_nid)
2828 spec->multiout.hp_nid =
2829 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2830 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2831 spec->multiout.extra_out_nid[0] =
2832 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2833
Takashi Iwai7085ec12009-10-02 09:03:58 +02002834 return 0;
2835}
2836
Takashi Iwai343a04b2011-07-06 14:28:39 +02002837static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002838 const char *pfx, int cidx,
2839 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002840{
Takashi Iwai97aaab72011-07-06 14:02:55 +02002841 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2842 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002843}
2844
Takashi Iwai343a04b2011-07-06 14:28:39 +02002845#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2846 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002847
2848/* create a mute-switch for the given mixer widget;
2849 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2850 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002851static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002852 const char *pfx, int cidx,
2853 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002854{
Takashi Iwai97aaab72011-07-06 14:02:55 +02002855 int type;
2856 unsigned long val;
2857 if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
2858 type = ALC_CTL_WIDGET_MUTE;
2859 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2860 } else {
2861 type = ALC_CTL_BIND_MUTE;
2862 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2863 }
2864 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002865}
2866
Takashi Iwai343a04b2011-07-06 14:28:39 +02002867#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2868 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002869
2870/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002871static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002872 const struct auto_pin_cfg *cfg)
2873{
2874 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002875 hda_nid_t nid, mix, pin;
2876 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002877
Takashi Iwaice764ab2011-04-27 16:35:23 +02002878 noutputs = cfg->line_outs;
2879 if (spec->multi_ios > 0)
2880 noutputs += spec->multi_ios;
2881
2882 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002883 const char *name;
2884 int index;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002885 nid = spec->multiout.dac_nids[i];
2886 if (!nid)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002887 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002888 if (i >= cfg->line_outs)
2889 pin = spec->multi_io[i - 1].pin;
2890 else
2891 pin = cfg->line_out_pins[i];
2892 mix = alc_auto_dac_to_mix(codec, pin, nid);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002893 if (!mix)
2894 continue;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002895 name = alc_get_line_out_pfx(spec, i, true, &index);
2896 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002897 /* Center/LFE */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002898 err = alc_auto_add_vol_ctl(codec, "Center", 0, nid, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002899 if (err < 0)
2900 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02002901 err = alc_auto_add_vol_ctl(codec, "LFE", 0, nid, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002902 if (err < 0)
2903 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02002904 err = alc_auto_add_sw_ctl(codec, "Center", 0, mix, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002905 if (err < 0)
2906 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02002907 err = alc_auto_add_sw_ctl(codec, "LFE", 0, mix, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002908 if (err < 0)
2909 return err;
2910 } else {
Takashi Iwai343a04b2011-07-06 14:28:39 +02002911 err = alc_auto_add_stereo_vol(codec, name, index, nid);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002912 if (err < 0)
2913 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02002914 err = alc_auto_add_stereo_sw(codec, name, index, mix);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002915 if (err < 0)
2916 return err;
2917 }
2918 }
2919 return 0;
2920}
2921
2922/* add playback controls for speaker and HP outputs */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002923static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002924 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002925{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002926 struct alc_spec *spec = codec->spec;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002927 hda_nid_t mix;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002928 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002929
2930 if (!pin)
2931 return 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002932 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02002933 /* the corresponding DAC is already occupied */
2934 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
2935 return 0; /* no way */
2936 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002937 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002938 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
2939 }
2940
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002941 mix = alc_auto_dac_to_mix(codec, pin, dac);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002942 if (!mix)
2943 return 0;
Takashi Iwai343a04b2011-07-06 14:28:39 +02002944 err = alc_auto_add_stereo_vol(codec, pfx, 0, dac);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002945 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02002946 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02002947 err = alc_auto_add_stereo_sw(codec, pfx, 0, mix);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002948 if (err < 0)
2949 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002950 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002951}
2952
Takashi Iwai343a04b2011-07-06 14:28:39 +02002953static int alc_auto_create_hp_out(struct hda_codec *codec)
2954{
2955 struct alc_spec *spec = codec->spec;
2956 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2957 spec->multiout.hp_nid,
2958 "Headphone");
2959}
2960
2961static int alc_auto_create_speaker_out(struct hda_codec *codec)
2962{
2963 struct alc_spec *spec = codec->spec;
2964 return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
2965 spec->multiout.extra_out_nid[0],
2966 "Speaker");
2967}
2968
Takashi Iwai343a04b2011-07-06 14:28:39 +02002969static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002970 hda_nid_t nid, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002971 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002972{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002973 int i, num;
Takashi Iwai343a04b2011-07-06 14:28:39 +02002974 hda_nid_t mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02002975 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002976
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002977 alc_set_pin_output(codec, nid, pin_type);
Takashi Iwaicd511552011-07-06 13:10:42 +02002978 nid = alc_go_down_to_selector(codec, nid);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002979 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002980 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002981 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002982 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02002983 mix = srcs[i];
2984 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002985 }
Takashi Iwaicd511552011-07-06 13:10:42 +02002986 if (!mix)
2987 return;
2988
2989 /* need the manual connection? */
2990 if (num > 1)
2991 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
2992 /* unmute mixer widget inputs */
2993 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2994 AMP_IN_UNMUTE(0));
2995 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2996 AMP_IN_UNMUTE(1));
2997 /* initialize volume */
2998 if (query_amp_caps(codec, dac, HDA_OUTPUT) & AC_AMPCAP_NUM_STEPS)
2999 nid = dac;
3000 else if (query_amp_caps(codec, mix, HDA_OUTPUT) & AC_AMPCAP_NUM_STEPS)
3001 nid = mix;
3002 else
3003 return;
3004 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3005 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003006}
3007
Takashi Iwai343a04b2011-07-06 14:28:39 +02003008static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003009{
3010 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003011 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003012 int i;
3013
3014 for (i = 0; i <= HDA_SIDE; i++) {
3015 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3016 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003017 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003018 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003019 }
3020}
3021
Takashi Iwai343a04b2011-07-06 14:28:39 +02003022static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003023{
3024 struct alc_spec *spec = codec->spec;
3025 hda_nid_t pin;
3026
3027 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003028 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003029 alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003030 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003031 pin = spec->autocfg.speaker_pins[0];
3032 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003033 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003034 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003035}
3036
Takashi Iwaice764ab2011-04-27 16:35:23 +02003037/*
3038 * multi-io helper
3039 */
3040static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3041 unsigned int location)
3042{
3043 struct alc_spec *spec = codec->spec;
3044 struct auto_pin_cfg *cfg = &spec->autocfg;
3045 int type, i, num_pins = 0;
3046
3047 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3048 for (i = 0; i < cfg->num_inputs; i++) {
3049 hda_nid_t nid = cfg->inputs[i].pin;
3050 hda_nid_t dac;
3051 unsigned int defcfg, caps;
3052 if (cfg->inputs[i].type != type)
3053 continue;
3054 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3055 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3056 continue;
3057 if (location && get_defcfg_location(defcfg) != location)
3058 continue;
3059 caps = snd_hda_query_pin_caps(codec, nid);
3060 if (!(caps & AC_PINCAP_OUT))
3061 continue;
3062 dac = alc_auto_look_for_dac(codec, nid);
3063 if (!dac)
3064 continue;
3065 spec->multi_io[num_pins].pin = nid;
3066 spec->multi_io[num_pins].dac = dac;
3067 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003068 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003069 }
3070 }
3071 spec->multiout.num_dacs = 1;
3072 if (num_pins < 2)
3073 return 0;
3074 return num_pins;
3075}
3076
3077static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3078 struct snd_ctl_elem_info *uinfo)
3079{
3080 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3081 struct alc_spec *spec = codec->spec;
3082
3083 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3084 uinfo->count = 1;
3085 uinfo->value.enumerated.items = spec->multi_ios + 1;
3086 if (uinfo->value.enumerated.item > spec->multi_ios)
3087 uinfo->value.enumerated.item = spec->multi_ios;
3088 sprintf(uinfo->value.enumerated.name, "%dch",
3089 (uinfo->value.enumerated.item + 1) * 2);
3090 return 0;
3091}
3092
3093static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3094 struct snd_ctl_elem_value *ucontrol)
3095{
3096 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3097 struct alc_spec *spec = codec->spec;
3098 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3099 return 0;
3100}
3101
3102static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3103{
3104 struct alc_spec *spec = codec->spec;
3105 hda_nid_t nid = spec->multi_io[idx].pin;
3106
3107 if (!spec->multi_io[idx].ctl_in)
3108 spec->multi_io[idx].ctl_in =
3109 snd_hda_codec_read(codec, nid, 0,
3110 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3111 if (output) {
3112 snd_hda_codec_update_cache(codec, nid, 0,
3113 AC_VERB_SET_PIN_WIDGET_CONTROL,
3114 PIN_OUT);
3115 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3116 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3117 HDA_AMP_MUTE, 0);
3118 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3119 } else {
3120 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3121 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3122 HDA_AMP_MUTE, HDA_AMP_MUTE);
3123 snd_hda_codec_update_cache(codec, nid, 0,
3124 AC_VERB_SET_PIN_WIDGET_CONTROL,
3125 spec->multi_io[idx].ctl_in);
3126 }
3127 return 0;
3128}
3129
3130static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3131 struct snd_ctl_elem_value *ucontrol)
3132{
3133 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3134 struct alc_spec *spec = codec->spec;
3135 int i, ch;
3136
3137 ch = ucontrol->value.enumerated.item[0];
3138 if (ch < 0 || ch > spec->multi_ios)
3139 return -EINVAL;
3140 if (ch == (spec->ext_channel_count - 1) / 2)
3141 return 0;
3142 spec->ext_channel_count = (ch + 1) * 2;
3143 for (i = 0; i < spec->multi_ios; i++)
3144 alc_set_multi_io(codec, i, i < ch);
3145 spec->multiout.max_channels = spec->ext_channel_count;
3146 return 1;
3147}
3148
Takashi Iwaia9111322011-05-02 11:30:18 +02003149static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003150 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3151 .name = "Channel Mode",
3152 .info = alc_auto_ch_mode_info,
3153 .get = alc_auto_ch_mode_get,
3154 .put = alc_auto_ch_mode_put,
3155};
3156
Takashi Iwaicb053a82011-06-27 11:32:07 +02003157static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
3158 int (*fill_dac)(struct hda_codec *))
Takashi Iwaice764ab2011-04-27 16:35:23 +02003159{
3160 struct alc_spec *spec = codec->spec;
3161 struct auto_pin_cfg *cfg = &spec->autocfg;
3162 unsigned int location, defcfg;
3163 int num_pins;
3164
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003165 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3166 /* use HP as primary out */
3167 cfg->speaker_outs = cfg->line_outs;
3168 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3169 sizeof(cfg->speaker_pins));
3170 cfg->line_outs = cfg->hp_outs;
3171 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3172 cfg->hp_outs = 0;
3173 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3174 cfg->line_out_type = AUTO_PIN_HP_OUT;
Takashi Iwaicb053a82011-06-27 11:32:07 +02003175 if (fill_dac)
3176 fill_dac(codec);
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003177 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003178 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003179 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003180 return 0;
3181
3182 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3183 location = get_defcfg_location(defcfg);
3184
3185 num_pins = alc_auto_fill_multi_ios(codec, location);
3186 if (num_pins > 0) {
3187 struct snd_kcontrol_new *knew;
3188
3189 knew = alc_kcontrol_new(spec);
3190 if (!knew)
3191 return -ENOMEM;
3192 *knew = alc_auto_channel_mode_enum;
3193 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3194 if (!knew->name)
3195 return -ENOMEM;
3196
3197 spec->multi_ios = num_pins;
3198 spec->ext_channel_count = 2;
3199 spec->multiout.num_dacs = num_pins + 1;
3200 }
3201 return 0;
3202}
3203
Takashi Iwai1d045db2011-07-07 18:23:21 +02003204/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3205 * active input pins
3206 */
3207static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3208{
3209 struct alc_spec *spec = codec->spec;
3210 const struct hda_input_mux *imux;
3211 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3212 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3213 int i, n, nums;
3214
3215 imux = spec->input_mux;
3216 if (!imux)
3217 return;
3218 if (spec->dyn_adc_switch)
3219 return;
3220
3221 nums = 0;
3222 for (n = 0; n < spec->num_adc_nids; n++) {
3223 hda_nid_t cap = spec->private_capsrc_nids[n];
3224 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3225 for (i = 0; i < imux->num_items; i++) {
3226 hda_nid_t pin = spec->imux_pins[i];
3227 if (pin) {
3228 if (get_connection_index(codec, cap, pin) < 0)
3229 break;
3230 } else if (num_conns <= imux->items[i].index)
3231 break;
3232 }
3233 if (i >= imux->num_items) {
3234 adc_nids[nums] = spec->private_adc_nids[n];
3235 capsrc_nids[nums++] = cap;
3236 }
3237 }
3238 if (!nums) {
3239 /* check whether ADC-switch is possible */
3240 if (!alc_check_dyn_adc_switch(codec)) {
3241 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3242 " using fallback 0x%x\n",
3243 codec->chip_name, spec->private_adc_nids[0]);
3244 spec->num_adc_nids = 1;
3245 spec->auto_mic = 0;
3246 return;
3247 }
3248 } else if (nums != spec->num_adc_nids) {
3249 memcpy(spec->private_adc_nids, adc_nids,
3250 nums * sizeof(hda_nid_t));
3251 memcpy(spec->private_capsrc_nids, capsrc_nids,
3252 nums * sizeof(hda_nid_t));
3253 spec->num_adc_nids = nums;
3254 }
3255
3256 if (spec->auto_mic)
3257 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3258 else if (spec->input_mux->num_items == 1)
3259 spec->num_adc_nids = 1; /* reduce to a single ADC */
3260}
3261
3262/*
3263 * initialize ADC paths
3264 */
3265static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3266{
3267 struct alc_spec *spec = codec->spec;
3268 hda_nid_t nid;
3269
3270 nid = spec->adc_nids[adc_idx];
3271 /* mute ADC */
3272 if (query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE) {
3273 snd_hda_codec_write(codec, nid, 0,
3274 AC_VERB_SET_AMP_GAIN_MUTE,
3275 AMP_IN_MUTE(0));
3276 return;
3277 }
3278 if (!spec->capsrc_nids)
3279 return;
3280 nid = spec->capsrc_nids[adc_idx];
3281 if (query_amp_caps(codec, nid, HDA_OUTPUT) & AC_AMPCAP_MUTE)
3282 snd_hda_codec_write(codec, nid, 0,
3283 AC_VERB_SET_AMP_GAIN_MUTE,
3284 AMP_OUT_MUTE);
3285}
3286
3287static void alc_auto_init_input_src(struct hda_codec *codec)
3288{
3289 struct alc_spec *spec = codec->spec;
3290 int c, nums;
3291
3292 for (c = 0; c < spec->num_adc_nids; c++)
3293 alc_auto_init_adc(codec, c);
3294 if (spec->dyn_adc_switch)
3295 nums = 1;
3296 else
3297 nums = spec->num_adc_nids;
3298 for (c = 0; c < nums; c++)
3299 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3300}
3301
3302/* add mic boosts if needed */
3303static int alc_auto_add_mic_boost(struct hda_codec *codec)
3304{
3305 struct alc_spec *spec = codec->spec;
3306 struct auto_pin_cfg *cfg = &spec->autocfg;
3307 int i, err;
3308 int type_idx = 0;
3309 hda_nid_t nid;
3310 const char *prev_label = NULL;
3311
3312 for (i = 0; i < cfg->num_inputs; i++) {
3313 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3314 break;
3315 nid = cfg->inputs[i].pin;
3316 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3317 const char *label;
3318 char boost_label[32];
3319
3320 label = hda_get_autocfg_input_label(codec, cfg, i);
3321 if (prev_label && !strcmp(label, prev_label))
3322 type_idx++;
3323 else
3324 type_idx = 0;
3325 prev_label = label;
3326
3327 snprintf(boost_label, sizeof(boost_label),
3328 "%s Boost Volume", label);
3329 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3330 boost_label, type_idx,
3331 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3332 if (err < 0)
3333 return err;
3334 }
3335 }
3336 return 0;
3337}
3338
3339/* select or unmute the given capsrc route */
3340static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3341 int idx)
3342{
3343 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3344 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3345 HDA_AMP_MUTE, 0);
3346 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3347 snd_hda_codec_write_cache(codec, cap, 0,
3348 AC_VERB_SET_CONNECT_SEL, idx);
3349 }
3350}
3351
3352/* set the default connection to that pin */
3353static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3354{
3355 struct alc_spec *spec = codec->spec;
3356 int i;
3357
3358 if (!pin)
3359 return 0;
3360 for (i = 0; i < spec->num_adc_nids; i++) {
3361 hda_nid_t cap = spec->capsrc_nids ?
3362 spec->capsrc_nids[i] : spec->adc_nids[i];
3363 int idx;
3364
3365 idx = get_connection_index(codec, cap, pin);
3366 if (idx < 0)
3367 continue;
3368 select_or_unmute_capsrc(codec, cap, idx);
3369 return i; /* return the found index */
3370 }
3371 return -1; /* not found */
3372}
3373
3374/* initialize some special cases for input sources */
3375static void alc_init_special_input_src(struct hda_codec *codec)
3376{
3377 struct alc_spec *spec = codec->spec;
3378 int i;
3379
3380 for (i = 0; i < spec->autocfg.num_inputs; i++)
3381 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3382}
3383
3384/* assign appropriate capture mixers */
3385static void set_capture_mixer(struct hda_codec *codec)
3386{
3387 struct alc_spec *spec = codec->spec;
3388 static const struct snd_kcontrol_new *caps[2][3] = {
3389 { alc_capture_mixer_nosrc1,
3390 alc_capture_mixer_nosrc2,
3391 alc_capture_mixer_nosrc3 },
3392 { alc_capture_mixer1,
3393 alc_capture_mixer2,
3394 alc_capture_mixer3 },
3395 };
3396
3397 /* check whether either of ADC or MUX has a volume control */
3398 if (!(query_amp_caps(codec, spec->adc_nids[0], HDA_INPUT) &
3399 AC_AMPCAP_NUM_STEPS)) {
3400 if (!spec->capsrc_nids)
3401 return; /* no volume */
3402 if (!(query_amp_caps(codec, spec->capsrc_nids[0], HDA_OUTPUT) &
3403 AC_AMPCAP_NUM_STEPS))
3404 return; /* no volume in capsrc, too */
3405 spec->vol_in_capsrc = 1;
3406 }
3407
3408 if (spec->num_adc_nids > 0) {
3409 int mux = 0;
3410 int num_adcs = 0;
3411
3412 if (spec->input_mux && spec->input_mux->num_items > 1)
3413 mux = 1;
3414 if (spec->auto_mic) {
3415 num_adcs = 1;
3416 mux = 0;
3417 } else if (spec->dyn_adc_switch)
3418 num_adcs = 1;
3419 if (!num_adcs) {
3420 if (spec->num_adc_nids > 3)
3421 spec->num_adc_nids = 3;
3422 else if (!spec->num_adc_nids)
3423 return;
3424 num_adcs = spec->num_adc_nids;
3425 }
3426 spec->cap_mixer = caps[mux][num_adcs - 1];
3427 }
3428}
3429
3430/*
3431 * Digital-beep handlers
3432 */
3433#ifdef CONFIG_SND_HDA_INPUT_BEEP
3434#define set_beep_amp(spec, nid, idx, dir) \
3435 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3436
3437static const struct snd_pci_quirk beep_white_list[] = {
3438 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3439 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3440 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3441 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3442 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3443 {}
3444};
3445
3446static inline int has_cdefine_beep(struct hda_codec *codec)
3447{
3448 struct alc_spec *spec = codec->spec;
3449 const struct snd_pci_quirk *q;
3450 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3451 if (q)
3452 return q->value;
3453 return spec->cdefine.enable_pcbeep;
3454}
3455#else
3456#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3457#define has_cdefine_beep(codec) 0
3458#endif
3459
3460/* parse the BIOS configuration and set up the alc_spec */
3461/* return 1 if successful, 0 if the proper config is not found,
3462 * or a negative error code
3463 */
3464static int alc880_parse_auto_config(struct hda_codec *codec)
3465{
3466 struct alc_spec *spec = codec->spec;
3467 int err;
3468 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3469
3470 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3471 alc880_ignore);
3472 if (err < 0)
3473 return err;
3474 if (!spec->autocfg.line_outs)
3475 return 0; /* can't find valid BIOS pin config */
3476
3477 err = alc_auto_fill_dac_nids(codec);
3478 if (err < 0)
3479 return err;
3480 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
3481 if (err < 0)
3482 return err;
3483 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
3484 if (err < 0)
3485 return err;
3486 err = alc_auto_create_hp_out(codec);
3487 if (err < 0)
3488 return err;
3489 err = alc_auto_create_speaker_out(codec);
3490 if (err < 0)
3491 return err;
3492 err = alc_auto_create_input_ctls(codec);
3493 if (err < 0)
3494 return err;
3495
3496 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3497
3498 alc_auto_parse_digital(codec);
3499
3500 if (spec->kctls.list)
3501 add_mixer(spec, spec->kctls.list);
3502
3503 alc_remove_invalid_adc_nids(codec);
3504
3505 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
3506 alc_auto_check_switches(codec);
3507
3508 return 1;
3509}
3510
3511/* additional initialization for auto-configuration model */
3512static void alc880_auto_init(struct hda_codec *codec)
3513{
3514 struct alc_spec *spec = codec->spec;
3515 alc_auto_init_multi_out(codec);
3516 alc_auto_init_extra_out(codec);
3517 alc_auto_init_analog_input(codec);
3518 alc_auto_init_input_src(codec);
3519 alc_auto_init_digital(codec);
3520 if (spec->unsol_event)
3521 alc_inithook(codec);
3522}
3523
3524#ifdef CONFIG_SND_HDA_POWER_SAVE
3525static const struct hda_amp_list alc880_loopbacks[] = {
3526 { 0x0b, HDA_INPUT, 0 },
3527 { 0x0b, HDA_INPUT, 1 },
3528 { 0x0b, HDA_INPUT, 2 },
3529 { 0x0b, HDA_INPUT, 3 },
3530 { 0x0b, HDA_INPUT, 4 },
3531 { } /* end */
3532};
3533#endif
3534
3535/*
3536 * board setups
3537 */
3538#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3539#define alc_board_config \
3540 snd_hda_check_board_config
3541#define alc_board_codec_sid_config \
3542 snd_hda_check_board_codec_sid_config
3543#include "alc_quirks.c"
3544#else
3545#define alc_board_config(codec, nums, models, tbl) -1
3546#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3547#define setup_preset(codec, x) /* NOP */
3548#endif
3549
3550/*
3551 * OK, here we have finally the patch for ALC880
3552 */
3553#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3554#include "alc880_quirks.c"
3555#endif
3556
3557static int patch_alc880(struct hda_codec *codec)
3558{
3559 struct alc_spec *spec;
3560 int board_config;
3561 int err;
3562
3563 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3564 if (spec == NULL)
3565 return -ENOMEM;
3566
3567 codec->spec = spec;
3568
3569 spec->mixer_nid = 0x0b;
3570
3571 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3572 alc880_models, alc880_cfg_tbl);
3573 if (board_config < 0) {
3574 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3575 codec->chip_name);
3576 board_config = ALC_MODEL_AUTO;
3577 }
3578
3579 if (board_config == ALC_MODEL_AUTO) {
3580 /* automatic parse from the BIOS config */
3581 err = alc880_parse_auto_config(codec);
3582 if (err < 0) {
3583 alc_free(codec);
3584 return err;
3585 }
3586#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3587 else if (!err) {
3588 printk(KERN_INFO
3589 "hda_codec: Cannot set up configuration "
3590 "from BIOS. Using 3-stack mode...\n");
3591 board_config = ALC880_3ST;
3592 }
3593#endif
3594 }
3595
3596 err = snd_hda_attach_beep_device(codec, 0x1);
3597 if (err < 0) {
3598 alc_free(codec);
3599 return err;
3600 }
3601
3602 if (board_config != ALC_MODEL_AUTO)
3603 setup_preset(codec, &alc880_presets[board_config]);
3604
3605 if (!spec->adc_nids && spec->input_mux) {
3606 alc_auto_fill_adc_caps(codec);
3607 alc_rebuild_imux_for_auto_mic(codec);
3608 alc_remove_invalid_adc_nids(codec);
3609 }
3610 set_capture_mixer(codec);
3611 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3612
3613 spec->vmaster_nid = 0x0c;
3614
3615 codec->patch_ops = alc_patch_ops;
3616 if (board_config == ALC_MODEL_AUTO)
3617 spec->init_hook = alc880_auto_init;
3618#ifdef CONFIG_SND_HDA_POWER_SAVE
3619 if (!spec->loopback.amplist)
3620 spec->loopback.amplist = alc880_loopbacks;
3621#endif
3622
3623 return 0;
3624}
3625
3626
3627/*
3628 * ALC260 support
3629 */
3630
3631/* convert from pin to volume-mixer widget */
3632static hda_nid_t alc260_pin_to_vol_mix(hda_nid_t nid)
3633{
3634 if (nid >= 0x0f && nid <= 0x11)
3635 return nid - 0x7;
3636 else if (nid >= 0x12 && nid <= 0x15)
3637 return 0x08;
3638 else
3639 return 0;
3640}
3641
3642static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
3643 const char *pfx, int *vol_bits)
3644{
3645 hda_nid_t nid_vol;
3646 unsigned long vol_val, sw_val;
3647 int chs, err;
3648
3649 nid_vol = alc260_pin_to_vol_mix(nid);
3650 if (!nid_vol)
3651 return 0; /* N/A */
3652 if (nid == 0x11)
3653 chs = 2;
3654 else
3655 chs = 3;
3656 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, chs, 0, HDA_OUTPUT);
3657 sw_val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
3658
3659 if (!(*vol_bits & (1 << nid_vol))) {
3660 /* first control for the volume widget */
3661 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
3662 if (err < 0)
3663 return err;
3664 *vol_bits |= (1 << nid_vol);
3665 }
3666 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
3667 if (err < 0)
3668 return err;
3669 return 1;
3670}
3671
3672/* add playback controls from the parsed DAC table */
3673static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
3674 const struct auto_pin_cfg *cfg)
3675{
3676 hda_nid_t nid;
3677 int err;
3678 int vols = 0;
3679
3680 spec->multiout.num_dacs = 1;
3681 spec->multiout.dac_nids = spec->private_dac_nids;
3682 spec->private_dac_nids[0] = 0x02;
3683
3684 nid = cfg->line_out_pins[0];
3685 if (nid) {
3686 const char *pfx;
3687 int index;
3688 pfx = alc_get_line_out_pfx(spec, 0, true, &index);
3689 err = alc260_add_playback_controls(spec, nid, pfx, &vols);
3690 if (err < 0)
3691 return err;
3692 }
3693
3694 nid = cfg->speaker_pins[0];
3695 if (nid) {
3696 err = alc260_add_playback_controls(spec, nid, "Speaker", &vols);
3697 if (err < 0)
3698 return err;
3699 }
3700
3701 nid = cfg->hp_pins[0];
3702 if (nid) {
3703 err = alc260_add_playback_controls(spec, nid, "Headphone",
3704 &vols);
3705 if (err < 0)
3706 return err;
3707 }
3708 return 0;
3709}
3710
3711static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
3712 hda_nid_t nid, int pin_type,
3713 int sel_idx)
3714{
3715 hda_nid_t mix;
3716
3717 alc_set_pin_output(codec, nid, pin_type);
3718 /* need the manual connection? */
3719 if (nid >= 0x12) {
3720 int idx = nid - 0x12;
3721 snd_hda_codec_write(codec, idx + 0x0b, 0,
3722 AC_VERB_SET_CONNECT_SEL, sel_idx);
3723 }
3724
3725 mix = alc260_pin_to_vol_mix(nid);
3726 if (!mix)
3727 return;
3728 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3729 AMP_OUT_ZERO);
3730 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3731 AMP_IN_UNMUTE(0));
3732 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3733 AMP_IN_UNMUTE(1));
3734}
3735
3736static void alc260_auto_init_multi_out(struct hda_codec *codec)
3737{
3738 struct alc_spec *spec = codec->spec;
3739 hda_nid_t nid;
3740
3741 nid = spec->autocfg.line_out_pins[0];
3742 if (nid) {
3743 int pin_type = get_pin_type(spec->autocfg.line_out_type);
3744 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
3745 }
3746
3747 nid = spec->autocfg.speaker_pins[0];
3748 if (nid)
3749 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3750
3751 nid = spec->autocfg.hp_pins[0];
3752 if (nid)
3753 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
3754}
3755
3756static int alc260_parse_auto_config(struct hda_codec *codec)
3757{
3758 struct alc_spec *spec = codec->spec;
3759 int err;
3760 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
3761
3762 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3763 alc260_ignore);
3764 if (err < 0)
3765 return err;
3766 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
3767 if (err < 0)
3768 return err;
3769 if (!spec->kctls.list)
3770 return 0; /* can't find valid BIOS pin config */
3771 err = alc_auto_create_input_ctls(codec);
3772 if (err < 0)
3773 return err;
3774
3775 spec->multiout.max_channels = 2;
3776
3777 alc_auto_parse_digital(codec);
3778
3779 if (spec->kctls.list)
3780 add_mixer(spec, spec->kctls.list);
3781
3782 alc_remove_invalid_adc_nids(codec);
3783
3784 alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
3785 alc_auto_check_switches(codec);
3786
3787 return 1;
3788}
3789
3790/* additional initialization for auto-configuration model */
3791static void alc260_auto_init(struct hda_codec *codec)
3792{
3793 struct alc_spec *spec = codec->spec;
3794 alc260_auto_init_multi_out(codec);
3795 alc_auto_init_analog_input(codec);
3796 alc_auto_init_input_src(codec);
3797 alc_auto_init_digital(codec);
3798 if (spec->unsol_event)
3799 alc_inithook(codec);
3800}
3801
3802#ifdef CONFIG_SND_HDA_POWER_SAVE
3803static const struct hda_amp_list alc260_loopbacks[] = {
3804 { 0x07, HDA_INPUT, 0 },
3805 { 0x07, HDA_INPUT, 1 },
3806 { 0x07, HDA_INPUT, 2 },
3807 { 0x07, HDA_INPUT, 3 },
3808 { 0x07, HDA_INPUT, 4 },
3809 { } /* end */
3810};
3811#endif
3812
3813/*
3814 * Pin config fixes
3815 */
3816enum {
3817 PINFIX_HP_DC5750,
3818};
3819
3820static const struct alc_fixup alc260_fixups[] = {
3821 [PINFIX_HP_DC5750] = {
3822 .type = ALC_FIXUP_PINS,
3823 .v.pins = (const struct alc_pincfg[]) {
3824 { 0x11, 0x90130110 }, /* speaker */
3825 { }
3826 }
3827 },
3828};
3829
3830static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3831 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3832 {}
3833};
3834
3835/*
3836 */
3837#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3838#include "alc260_quirks.c"
3839#endif
3840
3841static int patch_alc260(struct hda_codec *codec)
3842{
3843 struct alc_spec *spec;
3844 int err, board_config;
3845
3846 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3847 if (spec == NULL)
3848 return -ENOMEM;
3849
3850 codec->spec = spec;
3851
3852 spec->mixer_nid = 0x07;
3853
3854 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3855 alc260_models, alc260_cfg_tbl);
3856 if (board_config < 0) {
3857 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3858 codec->chip_name);
3859 board_config = ALC_MODEL_AUTO;
3860 }
3861
3862 if (board_config == ALC_MODEL_AUTO) {
3863 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3864 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3865 }
3866
3867 if (board_config == ALC_MODEL_AUTO) {
3868 /* automatic parse from the BIOS config */
3869 err = alc260_parse_auto_config(codec);
3870 if (err < 0) {
3871 alc_free(codec);
3872 return err;
3873 }
3874#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3875 else if (!err) {
3876 printk(KERN_INFO
3877 "hda_codec: Cannot set up configuration "
3878 "from BIOS. Using base mode...\n");
3879 board_config = ALC260_BASIC;
3880 }
3881#endif
3882 }
3883
3884 err = snd_hda_attach_beep_device(codec, 0x1);
3885 if (err < 0) {
3886 alc_free(codec);
3887 return err;
3888 }
3889
3890 if (board_config != ALC_MODEL_AUTO)
3891 setup_preset(codec, &alc260_presets[board_config]);
3892
3893 if (!spec->adc_nids && spec->input_mux) {
3894 alc_auto_fill_adc_caps(codec);
3895 alc_rebuild_imux_for_auto_mic(codec);
3896 alc_remove_invalid_adc_nids(codec);
3897 }
3898 set_capture_mixer(codec);
3899 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3900
3901 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3902
3903 spec->vmaster_nid = 0x08;
3904
3905 codec->patch_ops = alc_patch_ops;
3906 if (board_config == ALC_MODEL_AUTO)
3907 spec->init_hook = alc260_auto_init;
3908 spec->shutup = alc_eapd_shutup;
3909#ifdef CONFIG_SND_HDA_POWER_SAVE
3910 if (!spec->loopback.amplist)
3911 spec->loopback.amplist = alc260_loopbacks;
3912#endif
3913
3914 return 0;
3915}
3916
3917
3918/*
3919 * ALC882/883/885/888/889 support
3920 *
3921 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3922 * configuration. Each pin widget can choose any input DACs and a mixer.
3923 * Each ADC is connected from a mixer of all inputs. This makes possible
3924 * 6-channel independent captures.
3925 *
3926 * In addition, an independent DAC for the multi-playback (not used in this
3927 * driver yet).
3928 */
3929#ifdef CONFIG_SND_HDA_POWER_SAVE
3930#define alc882_loopbacks alc880_loopbacks
3931#endif
3932
3933/*
3934 * Pin config fixes
3935 */
3936enum {
3937 PINFIX_ABIT_AW9D_MAX,
3938 PINFIX_LENOVO_Y530,
3939 PINFIX_PB_M5210,
3940 PINFIX_ACER_ASPIRE_7736,
3941};
3942
3943static const struct alc_fixup alc882_fixups[] = {
3944 [PINFIX_ABIT_AW9D_MAX] = {
3945 .type = ALC_FIXUP_PINS,
3946 .v.pins = (const struct alc_pincfg[]) {
3947 { 0x15, 0x01080104 }, /* side */
3948 { 0x16, 0x01011012 }, /* rear */
3949 { 0x17, 0x01016011 }, /* clfe */
3950 { }
3951 }
3952 },
3953 [PINFIX_LENOVO_Y530] = {
3954 .type = ALC_FIXUP_PINS,
3955 .v.pins = (const struct alc_pincfg[]) {
3956 { 0x15, 0x99130112 }, /* rear int speakers */
3957 { 0x16, 0x99130111 }, /* subwoofer */
3958 { }
3959 }
3960 },
3961 [PINFIX_PB_M5210] = {
3962 .type = ALC_FIXUP_VERBS,
3963 .v.verbs = (const struct hda_verb[]) {
3964 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
3965 {}
3966 }
3967 },
3968 [PINFIX_ACER_ASPIRE_7736] = {
3969 .type = ALC_FIXUP_SKU,
3970 .v.sku = ALC_FIXUP_SKU_IGNORE,
3971 },
3972};
3973
3974static const struct snd_pci_quirk alc882_fixup_tbl[] = {
3975 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
3976 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
3977 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
3978 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
3979 {}
3980};
3981
3982/*
3983 * BIOS auto configuration
3984 */
3985/* almost identical with ALC880 parser... */
3986static int alc882_parse_auto_config(struct hda_codec *codec)
3987{
3988 struct alc_spec *spec = codec->spec;
3989 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
3990 int err;
3991
3992 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3993 alc882_ignore);
3994 if (err < 0)
3995 return err;
3996 if (!spec->autocfg.line_outs)
3997 return 0; /* can't find valid BIOS pin config */
3998
3999 err = alc_auto_fill_dac_nids(codec);
4000 if (err < 0)
4001 return err;
4002 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
4003 if (err < 0)
4004 return err;
4005 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
4006 if (err < 0)
4007 return err;
4008 err = alc_auto_create_hp_out(codec);
4009 if (err < 0)
4010 return err;
4011 err = alc_auto_create_speaker_out(codec);
4012 if (err < 0)
4013 return err;
4014 err = alc_auto_create_input_ctls(codec);
4015 if (err < 0)
4016 return err;
4017
4018 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4019
4020 alc_auto_parse_digital(codec);
4021
4022 if (spec->kctls.list)
4023 add_mixer(spec, spec->kctls.list);
4024
4025 err = alc_auto_add_mic_boost(codec);
4026 if (err < 0)
4027 return err;
4028
4029 alc_remove_invalid_adc_nids(codec);
4030
4031 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
4032 alc_auto_check_switches(codec);
4033
4034 return 1; /* config found */
4035}
4036
4037/* additional initialization for auto-configuration model */
4038static void alc882_auto_init(struct hda_codec *codec)
4039{
4040 struct alc_spec *spec = codec->spec;
4041 alc_auto_init_multi_out(codec);
4042 alc_auto_init_extra_out(codec);
4043 alc_auto_init_analog_input(codec);
4044 alc_auto_init_input_src(codec);
4045 alc_auto_init_digital(codec);
4046 if (spec->unsol_event)
4047 alc_inithook(codec);
4048}
4049
4050/*
4051 */
4052#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4053#include "alc882_quirks.c"
4054#endif
4055
4056static int patch_alc882(struct hda_codec *codec)
4057{
4058 struct alc_spec *spec;
4059 int err, board_config;
4060
4061 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4062 if (spec == NULL)
4063 return -ENOMEM;
4064
4065 codec->spec = spec;
4066
4067 spec->mixer_nid = 0x0b;
4068
4069 switch (codec->vendor_id) {
4070 case 0x10ec0882:
4071 case 0x10ec0885:
4072 break;
4073 default:
4074 /* ALC883 and variants */
4075 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4076 break;
4077 }
4078
4079 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
4080 alc882_models, alc882_cfg_tbl);
4081
4082 if (board_config < 0)
4083 board_config = alc_board_codec_sid_config(codec,
4084 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
4085
4086 if (board_config < 0) {
4087 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4088 codec->chip_name);
4089 board_config = ALC_MODEL_AUTO;
4090 }
4091
4092 if (board_config == ALC_MODEL_AUTO) {
4093 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
4094 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4095 }
4096
4097 alc_auto_parse_customize_define(codec);
4098
4099 if (board_config == ALC_MODEL_AUTO) {
4100 /* automatic parse from the BIOS config */
4101 err = alc882_parse_auto_config(codec);
4102 if (err < 0) {
4103 alc_free(codec);
4104 return err;
4105 }
4106#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4107 else if (!err) {
4108 printk(KERN_INFO
4109 "hda_codec: Cannot set up configuration "
4110 "from BIOS. Using base mode...\n");
4111 board_config = ALC882_3ST_DIG;
4112 }
4113#endif
4114 }
4115
4116 if (has_cdefine_beep(codec)) {
4117 err = snd_hda_attach_beep_device(codec, 0x1);
4118 if (err < 0) {
4119 alc_free(codec);
4120 return err;
4121 }
4122 }
4123
4124 if (board_config != ALC_MODEL_AUTO)
4125 setup_preset(codec, &alc882_presets[board_config]);
4126
4127 if (!spec->adc_nids && spec->input_mux) {
4128 alc_auto_fill_adc_caps(codec);
4129 alc_rebuild_imux_for_auto_mic(codec);
4130 alc_remove_invalid_adc_nids(codec);
4131 }
4132
4133 set_capture_mixer(codec);
4134
4135 if (has_cdefine_beep(codec))
4136 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
4137
4138 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4139
4140 spec->vmaster_nid = 0x0c;
4141
4142 codec->patch_ops = alc_patch_ops;
4143 if (board_config == ALC_MODEL_AUTO)
4144 spec->init_hook = alc882_auto_init;
4145
4146 alc_init_jacks(codec);
4147#ifdef CONFIG_SND_HDA_POWER_SAVE
4148 if (!spec->loopback.amplist)
4149 spec->loopback.amplist = alc882_loopbacks;
4150#endif
4151
4152 return 0;
4153}
4154
4155
4156/*
4157 * ALC262 support
4158 */
4159
4160/* We use two mixers depending on the output pin; 0x16 is a mono output
4161 * and thus it's bound with a different mixer.
4162 * This function returns which mixer amp should be used.
4163 */
4164static int alc262_check_volbit(hda_nid_t nid)
4165{
4166 if (!nid)
4167 return 0;
4168 else if (nid == 0x16)
4169 return 2;
4170 else
4171 return 1;
4172}
4173
4174static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
4175 const char *pfx, int *vbits, int idx)
4176{
4177 unsigned long val;
4178 int vbit;
4179
4180 vbit = alc262_check_volbit(nid);
4181 if (!vbit)
4182 return 0;
4183 if (*vbits & vbit) /* a volume control for this mixer already there */
4184 return 0;
4185 *vbits |= vbit;
4186 if (vbit == 2)
4187 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
4188 else
4189 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
4190 return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val);
4191}
4192
4193static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
4194 const char *pfx, int idx)
4195{
4196 unsigned long val;
4197
4198 if (!nid)
4199 return 0;
4200 if (nid == 0x16)
4201 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
4202 else
4203 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
4204 return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val);
4205}
4206
4207/* add playback controls from the parsed DAC table */
4208static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
4209 const struct auto_pin_cfg *cfg)
4210{
4211 const char *pfx;
4212 int vbits;
4213 int i, index, err;
4214
4215 spec->multiout.num_dacs = 1; /* only use one dac */
4216 spec->multiout.dac_nids = spec->private_dac_nids;
4217 spec->private_dac_nids[0] = 2;
4218
4219 for (i = 0; i < 2; i++) {
4220 pfx = alc_get_line_out_pfx(spec, i, true, &index);
4221 if (!pfx)
4222 pfx = "PCM";
4223 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx,
4224 index);
4225 if (err < 0)
4226 return err;
4227 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4228 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i],
4229 "Speaker", i);
4230 if (err < 0)
4231 return err;
4232 }
4233 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4234 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i],
4235 "Headphone", i);
4236 if (err < 0)
4237 return err;
4238 }
4239 }
4240
4241 vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
4242 alc262_check_volbit(cfg->speaker_pins[0]) |
4243 alc262_check_volbit(cfg->hp_pins[0]);
4244 vbits = 0;
4245 for (i = 0; i < 2; i++) {
4246 pfx = alc_get_line_out_pfx(spec, i, true, &index);
4247 if (!pfx)
4248 pfx = "PCM";
4249 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx,
4250 &vbits, i);
4251 if (err < 0)
4252 return err;
4253 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4254 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i],
4255 "Speaker", &vbits, i);
4256 if (err < 0)
4257 return err;
4258 }
4259 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4260 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i],
4261 "Headphone", &vbits, i);
4262 if (err < 0)
4263 return err;
4264 }
4265 }
4266 return 0;
4267}
4268
4269/*
4270 * BIOS auto configuration
4271 */
4272static int alc262_parse_auto_config(struct hda_codec *codec)
4273{
4274 struct alc_spec *spec = codec->spec;
4275 int err;
4276 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
4277
4278 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4279 alc262_ignore);
4280 if (err < 0)
4281 return err;
4282 if (!spec->autocfg.line_outs) {
4283 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
4284 spec->multiout.max_channels = 2;
4285 spec->no_analog = 1;
4286 goto dig_only;
4287 }
4288 return 0; /* can't find valid BIOS pin config */
4289 }
4290 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
4291 if (err < 0)
4292 return err;
4293 err = alc_auto_create_input_ctls(codec);
4294 if (err < 0)
4295 return err;
4296
4297 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4298
4299 dig_only:
4300 alc_auto_parse_digital(codec);
4301
4302 if (spec->kctls.list)
4303 add_mixer(spec, spec->kctls.list);
4304
4305 err = alc_auto_add_mic_boost(codec);
4306 if (err < 0)
4307 return err;
4308
4309 alc_remove_invalid_adc_nids(codec);
4310
4311 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
4312 alc_auto_check_switches(codec);
4313
4314 return 1;
4315}
4316
4317/*
4318 * Pin config fixes
4319 */
4320enum {
4321 PINFIX_FSC_H270,
4322 PINFIX_HP_Z200,
4323};
4324
4325static const struct alc_fixup alc262_fixups[] = {
4326 [PINFIX_FSC_H270] = {
4327 .type = ALC_FIXUP_PINS,
4328 .v.pins = (const struct alc_pincfg[]) {
4329 { 0x14, 0x99130110 }, /* speaker */
4330 { 0x15, 0x0221142f }, /* front HP */
4331 { 0x1b, 0x0121141f }, /* rear HP */
4332 { }
4333 }
4334 },
4335 [PINFIX_HP_Z200] = {
4336 .type = ALC_FIXUP_PINS,
4337 .v.pins = (const struct alc_pincfg[]) {
4338 { 0x16, 0x99130120 }, /* internal speaker */
4339 { }
4340 }
4341 },
4342};
4343
4344static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4345 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4346 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4347 {}
4348};
4349
4350
4351#ifdef CONFIG_SND_HDA_POWER_SAVE
4352#define alc262_loopbacks alc880_loopbacks
4353#endif
4354
4355/* init callback for auto-configuration model -- overriding the default init */
4356static void alc262_auto_init(struct hda_codec *codec)
4357{
4358 struct alc_spec *spec = codec->spec;
4359 alc_auto_init_multi_out(codec);
4360 alc_auto_init_extra_out(codec);
4361 alc_auto_init_analog_input(codec);
4362 alc_auto_init_input_src(codec);
4363 alc_auto_init_digital(codec);
4364 if (spec->unsol_event)
4365 alc_inithook(codec);
4366}
4367
4368/*
4369 */
4370#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4371#include "alc262_quirks.c"
4372#endif
4373
4374static int patch_alc262(struct hda_codec *codec)
4375{
4376 struct alc_spec *spec;
4377 int board_config;
4378 int err;
4379
4380 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4381 if (spec == NULL)
4382 return -ENOMEM;
4383
4384 codec->spec = spec;
4385
4386 spec->mixer_nid = 0x0b;
4387
4388#if 0
4389 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4390 * under-run
4391 */
4392 {
4393 int tmp;
4394 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4395 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4396 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4397 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4398 }
4399#endif
4400 alc_auto_parse_customize_define(codec);
4401
4402 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4403
4404 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4405 alc262_models, alc262_cfg_tbl);
4406
4407 if (board_config < 0) {
4408 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4409 codec->chip_name);
4410 board_config = ALC_MODEL_AUTO;
4411 }
4412
4413 if (board_config == ALC_MODEL_AUTO) {
4414 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4415 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4416 }
4417
4418 if (board_config == ALC_MODEL_AUTO) {
4419 /* automatic parse from the BIOS config */
4420 err = alc262_parse_auto_config(codec);
4421 if (err < 0) {
4422 alc_free(codec);
4423 return err;
4424 }
4425#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4426 else if (!err) {
4427 printk(KERN_INFO
4428 "hda_codec: Cannot set up configuration "
4429 "from BIOS. Using base mode...\n");
4430 board_config = ALC262_BASIC;
4431 }
4432#endif
4433 }
4434
4435 if (!spec->no_analog && has_cdefine_beep(codec)) {
4436 err = snd_hda_attach_beep_device(codec, 0x1);
4437 if (err < 0) {
4438 alc_free(codec);
4439 return err;
4440 }
4441 }
4442
4443 if (board_config != ALC_MODEL_AUTO)
4444 setup_preset(codec, &alc262_presets[board_config]);
4445
4446 if (!spec->adc_nids && spec->input_mux) {
4447 alc_auto_fill_adc_caps(codec);
4448 alc_rebuild_imux_for_auto_mic(codec);
4449 alc_remove_invalid_adc_nids(codec);
4450 }
4451 if (!spec->cap_mixer && !spec->no_analog)
4452 set_capture_mixer(codec);
4453 if (!spec->no_analog && has_cdefine_beep(codec))
4454 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
4455
4456 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4457
4458 spec->vmaster_nid = 0x0c;
4459
4460 codec->patch_ops = alc_patch_ops;
4461 if (board_config == ALC_MODEL_AUTO)
4462 spec->init_hook = alc262_auto_init;
4463 spec->shutup = alc_eapd_shutup;
4464
4465 alc_init_jacks(codec);
4466#ifdef CONFIG_SND_HDA_POWER_SAVE
4467 if (!spec->loopback.amplist)
4468 spec->loopback.amplist = alc262_loopbacks;
4469#endif
4470
4471 return 0;
4472}
4473
4474/*
4475 * ALC268
4476 */
4477/* create input playback/capture controls for the given pin */
4478static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
4479 const char *ctlname, int idx)
4480{
4481 hda_nid_t dac;
4482 int err;
4483
4484 switch (nid) {
4485 case 0x14:
4486 case 0x16:
4487 dac = 0x02;
4488 break;
4489 case 0x15:
4490 case 0x1a: /* ALC259/269 only */
4491 case 0x1b: /* ALC259/269 only */
4492 case 0x21: /* ALC269vb has this pin, too */
4493 dac = 0x03;
4494 break;
4495 default:
4496 snd_printd(KERN_WARNING "hda_codec: "
4497 "ignoring pin 0x%x as unknown\n", nid);
4498 return 0;
4499 }
4500 if (spec->multiout.dac_nids[0] != dac &&
4501 spec->multiout.dac_nids[1] != dac) {
4502 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
4503 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
4504 HDA_OUTPUT));
4505 if (err < 0)
4506 return err;
4507 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
4508 }
4509
4510 if (nid != 0x16)
4511 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
4512 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
4513 else /* mono */
4514 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
4515 HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
4516 if (err < 0)
4517 return err;
4518 return 0;
4519}
4520
4521/* add playback controls from the parsed DAC table */
4522static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
4523 const struct auto_pin_cfg *cfg)
4524{
4525 hda_nid_t nid;
4526 int err;
4527
4528 spec->multiout.dac_nids = spec->private_dac_nids;
4529
4530 nid = cfg->line_out_pins[0];
4531 if (nid) {
4532 const char *name;
4533 int index;
4534 name = alc_get_line_out_pfx(spec, 0, true, &index);
4535 err = alc268_new_analog_output(spec, nid, name, 0);
4536 if (err < 0)
4537 return err;
4538 }
4539
4540 nid = cfg->speaker_pins[0];
4541 if (nid == 0x1d) {
4542 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
4543 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
4544 if (err < 0)
4545 return err;
4546 } else if (nid) {
4547 err = alc268_new_analog_output(spec, nid, "Speaker", 0);
4548 if (err < 0)
4549 return err;
4550 }
4551 nid = cfg->hp_pins[0];
4552 if (nid) {
4553 err = alc268_new_analog_output(spec, nid, "Headphone", 0);
4554 if (err < 0)
4555 return err;
4556 }
4557
4558 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
4559 if (nid == 0x16) {
4560 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
4561 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
4562 if (err < 0)
4563 return err;
4564 }
4565 return 0;
4566}
4567
4568static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
4569 hda_nid_t nid, int pin_type)
4570{
4571 int idx;
4572
4573 alc_set_pin_output(codec, nid, pin_type);
4574 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
4575 return;
4576 if (nid == 0x14 || nid == 0x16)
4577 idx = 0;
4578 else
4579 idx = 1;
4580 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
4581}
4582
4583static void alc268_auto_init_dac(struct hda_codec *codec, hda_nid_t nid)
4584{
4585 if (!nid)
4586 return;
4587 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4588 AMP_OUT_ZERO);
4589}
4590
4591static void alc268_auto_init_multi_out(struct hda_codec *codec)
4592{
4593 struct alc_spec *spec = codec->spec;
4594 int i;
4595
4596 for (i = 0; i < spec->autocfg.line_outs; i++) {
4597 hda_nid_t nid = spec->autocfg.line_out_pins[i];
4598 int pin_type = get_pin_type(spec->autocfg.line_out_type);
4599 alc268_auto_set_output_and_unmute(codec, nid, pin_type);
4600 }
4601 /* mute DACs */
4602 for (i = 0; i < spec->multiout.num_dacs; i++)
4603 alc268_auto_init_dac(codec, spec->multiout.dac_nids[i]);
4604}
4605
4606static void alc268_auto_init_hp_out(struct hda_codec *codec)
4607{
4608 struct alc_spec *spec = codec->spec;
4609 hda_nid_t pin;
4610 int i;
4611
4612 for (i = 0; i < spec->autocfg.hp_outs; i++) {
4613 pin = spec->autocfg.hp_pins[i];
4614 alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
4615 }
4616 for (i = 0; i < spec->autocfg.speaker_outs; i++) {
4617 pin = spec->autocfg.speaker_pins[i];
4618 alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
4619 }
4620 if (spec->autocfg.mono_out_pin)
4621 snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0,
4622 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
4623 /* mute DACs */
4624 alc268_auto_init_dac(codec, spec->multiout.hp_nid);
4625 for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
4626 alc268_auto_init_dac(codec, spec->multiout.extra_out_nid[i]);
4627}
4628
4629static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
4630{
4631 struct alc_spec *spec = codec->spec;
4632 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
4633 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
4634 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
4635 unsigned int dac_vol1, dac_vol2;
4636
4637 if (line_nid == 0x1d || speaker_nid == 0x1d) {
4638 snd_hda_codec_write(codec, speaker_nid, 0,
4639 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
4640 /* mute mixer inputs from 0x1d */
4641 snd_hda_codec_write(codec, 0x0f, 0,
4642 AC_VERB_SET_AMP_GAIN_MUTE,
4643 AMP_IN_UNMUTE(1));
4644 snd_hda_codec_write(codec, 0x10, 0,
4645 AC_VERB_SET_AMP_GAIN_MUTE,
4646 AMP_IN_UNMUTE(1));
4647 } else {
4648 /* unmute mixer inputs from 0x1d */
4649 snd_hda_codec_write(codec, 0x0f, 0,
4650 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
4651 snd_hda_codec_write(codec, 0x10, 0,
4652 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
4653 }
4654
4655 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */
4656 if (line_nid == 0x14)
4657 dac_vol2 = AMP_OUT_ZERO;
4658 else if (line_nid == 0x15)
4659 dac_vol1 = AMP_OUT_ZERO;
4660 if (hp_nid == 0x14)
4661 dac_vol2 = AMP_OUT_ZERO;
4662 else if (hp_nid == 0x15)
4663 dac_vol1 = AMP_OUT_ZERO;
4664 if (line_nid != 0x16 || hp_nid != 0x16 ||
4665 spec->autocfg.line_out_pins[1] != 0x16 ||
4666 spec->autocfg.line_out_pins[2] != 0x16)
4667 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
4668
4669 snd_hda_codec_write(codec, 0x02, 0,
4670 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
4671 snd_hda_codec_write(codec, 0x03, 0,
4672 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
4673}
4674
4675/* bind Beep switches of both NID 0x0f and 0x10 */
4676static const struct hda_bind_ctls alc268_bind_beep_sw = {
4677 .ops = &snd_hda_bind_sw,
4678 .values = {
4679 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4680 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4681 0
4682 },
4683};
4684
4685static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4686 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4687 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4688 { }
4689};
4690
4691/* set PCBEEP vol = 0, mute connections */
4692static const struct hda_verb alc268_beep_init_verbs[] = {
4693 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4694 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4695 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4696 { }
4697};
4698
4699/*
4700 * BIOS auto configuration
4701 */
4702static int alc268_parse_auto_config(struct hda_codec *codec)
4703{
4704 struct alc_spec *spec = codec->spec;
4705 int err;
4706 static const hda_nid_t alc268_ignore[] = { 0 };
4707
4708 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4709 alc268_ignore);
4710 if (err < 0)
4711 return err;
4712 if (!spec->autocfg.line_outs) {
4713 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
4714 spec->multiout.max_channels = 2;
4715 spec->no_analog = 1;
4716 goto dig_only;
4717 }
4718 return 0; /* can't find valid BIOS pin config */
4719 }
4720 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
4721 if (err < 0)
4722 return err;
4723 err = alc_auto_create_input_ctls(codec);
4724 if (err < 0)
4725 return err;
4726
4727 spec->multiout.max_channels = 2;
4728
4729 dig_only:
4730 /* digital only support output */
4731 alc_auto_parse_digital(codec);
4732 if (spec->kctls.list)
4733 add_mixer(spec, spec->kctls.list);
4734
4735 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4736 add_mixer(spec, alc268_beep_mixer);
4737 add_verb(spec, alc268_beep_init_verbs);
4738 }
4739
4740 err = alc_auto_add_mic_boost(codec);
4741 if (err < 0)
4742 return err;
4743
4744 alc_remove_invalid_adc_nids(codec);
4745
4746 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
4747 alc_auto_check_switches(codec);
4748
4749 return 1;
4750}
4751
4752/* init callback for auto-configuration model -- overriding the default init */
4753static void alc268_auto_init(struct hda_codec *codec)
4754{
4755 struct alc_spec *spec = codec->spec;
4756 alc268_auto_init_multi_out(codec);
4757 alc268_auto_init_hp_out(codec);
4758 alc268_auto_init_mono_speaker_out(codec);
4759 alc_auto_init_analog_input(codec);
4760 alc_auto_init_input_src(codec);
4761 alc_auto_init_digital(codec);
4762 if (spec->unsol_event)
4763 alc_inithook(codec);
4764}
4765
4766/*
4767 */
4768#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4769#include "alc268_quirks.c"
4770#endif
4771
4772static int patch_alc268(struct hda_codec *codec)
4773{
4774 struct alc_spec *spec;
4775 int board_config;
4776 int i, has_beep, err;
4777
4778 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4779 if (spec == NULL)
4780 return -ENOMEM;
4781
4782 codec->spec = spec;
4783
4784 /* ALC268 has no aa-loopback mixer */
4785
4786 board_config = alc_board_config(codec, ALC268_MODEL_LAST,
4787 alc268_models, alc268_cfg_tbl);
4788
4789 if (board_config < 0)
4790 board_config = alc_board_codec_sid_config(codec,
4791 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
4792
4793 if (board_config < 0) {
4794 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4795 codec->chip_name);
4796 board_config = ALC_MODEL_AUTO;
4797 }
4798
4799 if (board_config == ALC_MODEL_AUTO) {
4800 /* automatic parse from the BIOS config */
4801 err = alc268_parse_auto_config(codec);
4802 if (err < 0) {
4803 alc_free(codec);
4804 return err;
4805 }
4806#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4807 else if (!err) {
4808 printk(KERN_INFO
4809 "hda_codec: Cannot set up configuration "
4810 "from BIOS. Using base mode...\n");
4811 board_config = ALC268_3ST;
4812 }
4813#endif
4814 }
4815
4816 if (board_config != ALC_MODEL_AUTO)
4817 setup_preset(codec, &alc268_presets[board_config]);
4818
4819 has_beep = 0;
4820 for (i = 0; i < spec->num_mixers; i++) {
4821 if (spec->mixers[i] == alc268_beep_mixer) {
4822 has_beep = 1;
4823 break;
4824 }
4825 }
4826
4827 if (has_beep) {
4828 err = snd_hda_attach_beep_device(codec, 0x1);
4829 if (err < 0) {
4830 alc_free(codec);
4831 return err;
4832 }
4833 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4834 /* override the amp caps for beep generator */
4835 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4836 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4837 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4838 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4839 (0 << AC_AMPCAP_MUTE_SHIFT));
4840 }
4841
4842 if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
4843 alc_auto_fill_adc_caps(codec);
4844 alc_rebuild_imux_for_auto_mic(codec);
4845 alc_remove_invalid_adc_nids(codec);
4846 }
4847
4848 if (!spec->cap_mixer && !spec->no_analog)
4849 set_capture_mixer(codec);
4850
4851 spec->vmaster_nid = 0x02;
4852
4853 codec->patch_ops = alc_patch_ops;
4854 if (board_config == ALC_MODEL_AUTO)
4855 spec->init_hook = alc268_auto_init;
4856 spec->shutup = alc_eapd_shutup;
4857
4858 alc_init_jacks(codec);
4859
4860 return 0;
4861}
4862
4863/*
4864 * ALC269
4865 */
4866#define alc269_auto_create_multi_out_ctls \
4867 alc268_auto_create_multi_out_ctls
4868
4869#ifdef CONFIG_SND_HDA_POWER_SAVE
4870#define alc269_loopbacks alc880_loopbacks
4871#endif
4872
4873static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4874 .substreams = 1,
4875 .channels_min = 2,
4876 .channels_max = 8,
4877 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4878 /* NID is set in alc_build_pcms */
4879 .ops = {
4880 .open = alc_playback_pcm_open,
4881 .prepare = alc_playback_pcm_prepare,
4882 .cleanup = alc_playback_pcm_cleanup
4883 },
4884};
4885
4886static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4887 .substreams = 1,
4888 .channels_min = 2,
4889 .channels_max = 2,
4890 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4891 /* NID is set in alc_build_pcms */
4892};
4893
4894#ifdef CONFIG_SND_HDA_POWER_SAVE
4895static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4896{
4897 switch (codec->subsystem_id) {
4898 case 0x103c1586:
4899 return 1;
4900 }
4901 return 0;
4902}
4903
4904static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4905{
4906 /* update mute-LED according to the speaker mute state */
4907 if (nid == 0x01 || nid == 0x14) {
4908 int pinval;
4909 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4910 HDA_AMP_MUTE)
4911 pinval = 0x24;
4912 else
4913 pinval = 0x20;
4914 /* mic2 vref pin is used for mute LED control */
4915 snd_hda_codec_update_cache(codec, 0x19, 0,
4916 AC_VERB_SET_PIN_WIDGET_CONTROL,
4917 pinval);
4918 }
4919 return alc_check_power_status(codec, nid);
4920}
4921#endif /* CONFIG_SND_HDA_POWER_SAVE */
4922
4923/* different alc269-variants */
4924enum {
4925 ALC269_TYPE_ALC269VA,
4926 ALC269_TYPE_ALC269VB,
4927 ALC269_TYPE_ALC269VC,
4928};
4929
4930/*
4931 * BIOS auto configuration
4932 */
4933static int alc269_parse_auto_config(struct hda_codec *codec)
4934{
4935 struct alc_spec *spec = codec->spec;
4936 int err;
4937 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
4938
4939 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4940 alc269_ignore);
4941 if (err < 0)
4942 return err;
4943
4944 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
4945 if (err < 0)
4946 return err;
4947 err = alc_auto_create_input_ctls(codec);
4948 if (err < 0)
4949 return err;
4950
4951 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4952
4953 alc_auto_parse_digital(codec);
4954
4955 if (spec->kctls.list)
4956 add_mixer(spec, spec->kctls.list);
4957
4958 alc_remove_invalid_adc_nids(codec);
4959
4960 if (spec->codec_variant != ALC269_TYPE_ALC269VA)
4961 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
4962 else
4963 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
4964 alc_auto_check_switches(codec);
4965
4966 err = alc_auto_add_mic_boost(codec);
4967 if (err < 0)
4968 return err;
4969
4970 if (!spec->cap_mixer && !spec->no_analog)
4971 set_capture_mixer(codec);
4972
4973 return 1;
4974}
4975
4976#define alc269_auto_init_multi_out alc268_auto_init_multi_out
4977#define alc269_auto_init_hp_out alc268_auto_init_hp_out
4978
4979
4980/* init callback for auto-configuration model -- overriding the default init */
4981static void alc269_auto_init(struct hda_codec *codec)
4982{
4983 struct alc_spec *spec = codec->spec;
4984 alc269_auto_init_multi_out(codec);
4985 alc269_auto_init_hp_out(codec);
4986 alc_auto_init_analog_input(codec);
4987 alc_auto_init_input_src(codec);
4988 alc_auto_init_digital(codec);
4989 if (spec->unsol_event)
4990 alc_inithook(codec);
4991}
4992
4993static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4994{
4995 int val = alc_read_coef_idx(codec, 0x04);
4996 if (power_up)
4997 val |= 1 << 11;
4998 else
4999 val &= ~(1 << 11);
5000 alc_write_coef_idx(codec, 0x04, val);
5001}
5002
5003static void alc269_shutup(struct hda_codec *codec)
5004{
5005 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
5006 alc269_toggle_power_output(codec, 0);
5007 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
5008 alc269_toggle_power_output(codec, 0);
5009 msleep(150);
5010 }
5011}
5012
5013#ifdef SND_HDA_NEEDS_RESUME
5014static int alc269_resume(struct hda_codec *codec)
5015{
5016 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
5017 alc269_toggle_power_output(codec, 0);
5018 msleep(150);
5019 }
5020
5021 codec->patch_ops.init(codec);
5022
5023 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
5024 alc269_toggle_power_output(codec, 1);
5025 msleep(200);
5026 }
5027
5028 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
5029 alc269_toggle_power_output(codec, 1);
5030
5031 snd_hda_codec_resume_amp(codec);
5032 snd_hda_codec_resume_cache(codec);
5033 hda_call_check_power_status(codec, 0x01);
5034 return 0;
5035}
5036#endif /* SND_HDA_NEEDS_RESUME */
5037
5038static void alc269_fixup_hweq(struct hda_codec *codec,
5039 const struct alc_fixup *fix, int action)
5040{
5041 int coef;
5042
5043 if (action != ALC_FIXUP_ACT_INIT)
5044 return;
5045 coef = alc_read_coef_idx(codec, 0x1e);
5046 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
5047}
5048
5049static void alc271_fixup_dmic(struct hda_codec *codec,
5050 const struct alc_fixup *fix, int action)
5051{
5052 static const struct hda_verb verbs[] = {
5053 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
5054 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
5055 {}
5056 };
5057 unsigned int cfg;
5058
5059 if (strcmp(codec->chip_name, "ALC271X"))
5060 return;
5061 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
5062 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
5063 snd_hda_sequence_write(codec, verbs);
5064}
5065
5066enum {
5067 ALC269_FIXUP_SONY_VAIO,
5068 ALC275_FIXUP_SONY_VAIO_GPIO2,
5069 ALC269_FIXUP_DELL_M101Z,
5070 ALC269_FIXUP_SKU_IGNORE,
5071 ALC269_FIXUP_ASUS_G73JW,
5072 ALC269_FIXUP_LENOVO_EAPD,
5073 ALC275_FIXUP_SONY_HWEQ,
5074 ALC271_FIXUP_DMIC,
5075};
5076
5077static const struct alc_fixup alc269_fixups[] = {
5078 [ALC269_FIXUP_SONY_VAIO] = {
5079 .type = ALC_FIXUP_VERBS,
5080 .v.verbs = (const struct hda_verb[]) {
5081 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
5082 {}
5083 }
5084 },
5085 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
5086 .type = ALC_FIXUP_VERBS,
5087 .v.verbs = (const struct hda_verb[]) {
5088 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
5089 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
5090 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
5091 { }
5092 },
5093 .chained = true,
5094 .chain_id = ALC269_FIXUP_SONY_VAIO
5095 },
5096 [ALC269_FIXUP_DELL_M101Z] = {
5097 .type = ALC_FIXUP_VERBS,
5098 .v.verbs = (const struct hda_verb[]) {
5099 /* Enables internal speaker */
5100 {0x20, AC_VERB_SET_COEF_INDEX, 13},
5101 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
5102 {}
5103 }
5104 },
5105 [ALC269_FIXUP_SKU_IGNORE] = {
5106 .type = ALC_FIXUP_SKU,
5107 .v.sku = ALC_FIXUP_SKU_IGNORE,
5108 },
5109 [ALC269_FIXUP_ASUS_G73JW] = {
5110 .type = ALC_FIXUP_PINS,
5111 .v.pins = (const struct alc_pincfg[]) {
5112 { 0x17, 0x99130111 }, /* subwoofer */
5113 { }
5114 }
5115 },
5116 [ALC269_FIXUP_LENOVO_EAPD] = {
5117 .type = ALC_FIXUP_VERBS,
5118 .v.verbs = (const struct hda_verb[]) {
5119 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5120 {}
5121 }
5122 },
5123 [ALC275_FIXUP_SONY_HWEQ] = {
5124 .type = ALC_FIXUP_FUNC,
5125 .v.func = alc269_fixup_hweq,
5126 .chained = true,
5127 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
5128 },
5129 [ALC271_FIXUP_DMIC] = {
5130 .type = ALC_FIXUP_FUNC,
5131 .v.func = alc271_fixup_dmic,
5132 },
5133};
5134
5135static const struct snd_pci_quirk alc269_fixup_tbl[] = {
5136 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
5137 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
5138 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
5139 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
5140 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
5141 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
5142 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
5143 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
5144 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
5145 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
5146 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
5147 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
5148 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
5149 {}
5150};
5151
5152
5153static int alc269_fill_coef(struct hda_codec *codec)
5154{
5155 int val;
5156
5157 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
5158 alc_write_coef_idx(codec, 0xf, 0x960b);
5159 alc_write_coef_idx(codec, 0xe, 0x8817);
5160 }
5161
5162 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
5163 alc_write_coef_idx(codec, 0xf, 0x960b);
5164 alc_write_coef_idx(codec, 0xe, 0x8814);
5165 }
5166
5167 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
5168 val = alc_read_coef_idx(codec, 0x04);
5169 /* Power up output pin */
5170 alc_write_coef_idx(codec, 0x04, val | (1<<11));
5171 }
5172
5173 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
5174 val = alc_read_coef_idx(codec, 0xd);
5175 if ((val & 0x0c00) >> 10 != 0x1) {
5176 /* Capless ramp up clock control */
5177 alc_write_coef_idx(codec, 0xd, val | (1<<10));
5178 }
5179 val = alc_read_coef_idx(codec, 0x17);
5180 if ((val & 0x01c0) >> 6 != 0x4) {
5181 /* Class D power on reset */
5182 alc_write_coef_idx(codec, 0x17, val | (1<<7));
5183 }
5184 }
5185
5186 val = alc_read_coef_idx(codec, 0xd); /* Class D */
5187 alc_write_coef_idx(codec, 0xd, val | (1<<14));
5188
5189 val = alc_read_coef_idx(codec, 0x4); /* HP */
5190 alc_write_coef_idx(codec, 0x4, val | (1<<11));
5191
5192 return 0;
5193}
5194
5195/*
5196 */
5197#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5198#include "alc269_quirks.c"
5199#endif
5200
5201static int patch_alc269(struct hda_codec *codec)
5202{
5203 struct alc_spec *spec;
5204 int board_config, coef;
5205 int err;
5206
5207 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5208 if (spec == NULL)
5209 return -ENOMEM;
5210
5211 codec->spec = spec;
5212
5213 spec->mixer_nid = 0x0b;
5214
5215 alc_auto_parse_customize_define(codec);
5216
5217 if (codec->vendor_id == 0x10ec0269) {
5218 spec->codec_variant = ALC269_TYPE_ALC269VA;
5219 coef = alc_read_coef_idx(codec, 0);
5220 if ((coef & 0x00f0) == 0x0010) {
5221 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
5222 spec->cdefine.platform_type == 1) {
5223 alc_codec_rename(codec, "ALC271X");
5224 } else if ((coef & 0xf000) == 0x2000) {
5225 alc_codec_rename(codec, "ALC259");
5226 } else if ((coef & 0xf000) == 0x3000) {
5227 alc_codec_rename(codec, "ALC258");
5228 } else if ((coef & 0xfff0) == 0x3010) {
5229 alc_codec_rename(codec, "ALC277");
5230 } else {
5231 alc_codec_rename(codec, "ALC269VB");
5232 }
5233 spec->codec_variant = ALC269_TYPE_ALC269VB;
5234 } else if ((coef & 0x00f0) == 0x0020) {
5235 if (coef == 0xa023)
5236 alc_codec_rename(codec, "ALC259");
5237 else if (coef == 0x6023)
5238 alc_codec_rename(codec, "ALC281X");
5239 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
5240 codec->bus->pci->subsystem_device == 0x21f3)
5241 alc_codec_rename(codec, "ALC3202");
5242 else
5243 alc_codec_rename(codec, "ALC269VC");
5244 spec->codec_variant = ALC269_TYPE_ALC269VC;
5245 } else
5246 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5247 alc269_fill_coef(codec);
5248 }
5249
5250 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
5251 alc269_models, alc269_cfg_tbl);
5252
5253 if (board_config < 0) {
5254 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5255 codec->chip_name);
5256 board_config = ALC_MODEL_AUTO;
5257 }
5258
5259 if (board_config == ALC_MODEL_AUTO) {
5260 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
5261 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5262 }
5263
5264 if (board_config == ALC_MODEL_AUTO) {
5265 /* automatic parse from the BIOS config */
5266 err = alc269_parse_auto_config(codec);
5267 if (err < 0) {
5268 alc_free(codec);
5269 return err;
5270 }
5271#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5272 else if (!err) {
5273 printk(KERN_INFO
5274 "hda_codec: Cannot set up configuration "
5275 "from BIOS. Using base mode...\n");
5276 board_config = ALC269_BASIC;
5277 }
5278#endif
5279 }
5280
5281 if (has_cdefine_beep(codec)) {
5282 err = snd_hda_attach_beep_device(codec, 0x1);
5283 if (err < 0) {
5284 alc_free(codec);
5285 return err;
5286 }
5287 }
5288
5289 if (board_config != ALC_MODEL_AUTO)
5290 setup_preset(codec, &alc269_presets[board_config]);
5291
5292#if 0
5293 if (board_config == ALC269_QUANTA_FL1) {
5294 /* Due to a hardware problem on Lenovo Ideadpad, we need to
5295 * fix the sample rate of analog I/O to 44.1kHz
5296 */
5297 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
5298 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
5299 }
5300#endif
5301
5302 if (!spec->adc_nids) { /* wasn't filled automatically? use default */
5303 alc_auto_fill_adc_caps(codec);
5304 alc_rebuild_imux_for_auto_mic(codec);
5305 alc_remove_invalid_adc_nids(codec);
5306 }
5307
5308 if (!spec->cap_mixer)
5309 set_capture_mixer(codec);
5310 if (has_cdefine_beep(codec))
5311 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5312
5313 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5314
5315 spec->vmaster_nid = 0x02;
5316
5317 codec->patch_ops = alc_patch_ops;
5318#ifdef SND_HDA_NEEDS_RESUME
5319 codec->patch_ops.resume = alc269_resume;
5320#endif
5321 if (board_config == ALC_MODEL_AUTO)
5322 spec->init_hook = alc269_auto_init;
5323 spec->shutup = alc269_shutup;
5324
5325 alc_init_jacks(codec);
5326#ifdef CONFIG_SND_HDA_POWER_SAVE
5327 if (!spec->loopback.amplist)
5328 spec->loopback.amplist = alc269_loopbacks;
5329 if (alc269_mic2_for_mute_led(codec))
5330 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
5331#endif
5332
5333 return 0;
5334}
5335
5336/*
5337 * ALC861
5338 */
5339
5340static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
5341{
5342 struct alc_spec *spec = codec->spec;
5343 hda_nid_t mix, srcs[5];
5344 int i, num;
5345
5346 if (snd_hda_get_connections(codec, pin, &mix, 1) != 1)
5347 return 0;
5348 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
5349 if (num < 0)
5350 return 0;
5351 for (i = 0; i < num; i++) {
5352 unsigned int type;
5353 type = get_wcaps_type(get_wcaps(codec, srcs[i]));
5354 if (type != AC_WID_AUD_OUT)
5355 continue;
5356 if (!found_in_nid_list(srcs[i], spec->multiout.dac_nids,
5357 spec->multiout.num_dacs))
5358 return srcs[i];
5359 }
5360 return 0;
5361}
5362
5363/* fill in the dac_nids table from the parsed pin configuration */
5364static int alc861_auto_fill_dac_nids(struct hda_codec *codec)
5365{
5366 struct alc_spec *spec = codec->spec;
5367 const struct auto_pin_cfg *cfg = &spec->autocfg;
5368 int i;
5369 hda_nid_t nid, dac;
5370
5371 spec->multiout.dac_nids = spec->private_dac_nids;
5372 for (i = 0; i < cfg->line_outs; i++) {
5373 nid = cfg->line_out_pins[i];
5374 dac = alc861_look_for_dac(codec, nid);
5375 if (!dac)
5376 continue;
5377 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
5378 }
5379 return 0;
5380}
5381
5382static int __alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
5383 hda_nid_t nid, int idx, unsigned int chs)
5384{
5385 return __add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, idx,
5386 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
5387}
5388
5389#define alc861_create_out_sw(codec, pfx, nid, chs) \
5390 __alc861_create_out_sw(codec, pfx, nid, 0, chs)
5391
5392/* add playback controls from the parsed DAC table */
5393static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
5394 const struct auto_pin_cfg *cfg)
5395{
5396 struct alc_spec *spec = codec->spec;
5397 hda_nid_t nid;
5398 int i, err, noutputs;
5399
5400 noutputs = cfg->line_outs;
5401 if (spec->multi_ios > 0)
5402 noutputs += spec->multi_ios;
5403
5404 for (i = 0; i < noutputs; i++) {
5405 const char *name;
5406 int index;
5407 nid = spec->multiout.dac_nids[i];
5408 if (!nid)
5409 continue;
5410 name = alc_get_line_out_pfx(spec, i, true, &index);
5411 if (!name) {
5412 /* Center/LFE */
5413 err = alc861_create_out_sw(codec, "Center", nid, 1);
5414 if (err < 0)
5415 return err;
5416 err = alc861_create_out_sw(codec, "LFE", nid, 2);
5417 if (err < 0)
5418 return err;
5419 } else {
5420 err = __alc861_create_out_sw(codec, name, nid, index, 3);
5421 if (err < 0)
5422 return err;
5423 }
5424 }
5425 return 0;
5426}
5427
5428static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
5429{
5430 struct alc_spec *spec = codec->spec;
5431 int err;
5432 hda_nid_t nid;
5433
5434 if (!pin)
5435 return 0;
5436
5437 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
5438 nid = alc861_look_for_dac(codec, pin);
5439 if (nid) {
5440 err = alc861_create_out_sw(codec, "Headphone", nid, 3);
5441 if (err < 0)
5442 return err;
5443 spec->multiout.hp_nid = nid;
5444 }
5445 }
5446 return 0;
5447}
5448
5449static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
5450 hda_nid_t nid,
5451 int pin_type, hda_nid_t dac)
5452{
5453 hda_nid_t mix, srcs[5];
5454 int i, num;
5455
5456 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5457 pin_type);
5458 snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
5459 AMP_OUT_UNMUTE);
5460 if (snd_hda_get_connections(codec, nid, &mix, 1) != 1)
5461 return;
5462 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
5463 if (num < 0)
5464 return;
5465 for (i = 0; i < num; i++) {
5466 unsigned int mute;
5467 if (srcs[i] == dac || srcs[i] == 0x15)
5468 mute = AMP_IN_UNMUTE(i);
5469 else
5470 mute = AMP_IN_MUTE(i);
5471 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
5472 mute);
5473 }
5474}
5475
5476static void alc861_auto_init_multi_out(struct hda_codec *codec)
5477{
5478 struct alc_spec *spec = codec->spec;
5479 int i;
5480
5481 for (i = 0; i < spec->autocfg.line_outs + spec->multi_ios; i++) {
5482 hda_nid_t nid = spec->autocfg.line_out_pins[i];
5483 int pin_type = get_pin_type(spec->autocfg.line_out_type);
5484 if (nid)
5485 alc861_auto_set_output_and_unmute(codec, nid, pin_type,
5486 spec->multiout.dac_nids[i]);
5487 }
5488}
5489
5490static void alc861_auto_init_hp_out(struct hda_codec *codec)
5491{
5492 struct alc_spec *spec = codec->spec;
5493
5494 if (spec->autocfg.hp_outs)
5495 alc861_auto_set_output_and_unmute(codec,
5496 spec->autocfg.hp_pins[0],
5497 PIN_HP,
5498 spec->multiout.hp_nid);
5499 if (spec->autocfg.speaker_outs)
5500 alc861_auto_set_output_and_unmute(codec,
5501 spec->autocfg.speaker_pins[0],
5502 PIN_OUT,
5503 spec->multiout.dac_nids[0]);
5504}
5505
5506/* parse the BIOS configuration and set up the alc_spec */
5507/* return 1 if successful, 0 if the proper config is not found,
5508 * or a negative error code
5509 */
5510static int alc861_parse_auto_config(struct hda_codec *codec)
5511{
5512 struct alc_spec *spec = codec->spec;
5513 int err;
5514 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
5515
5516 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5517 alc861_ignore);
5518 if (err < 0)
5519 return err;
5520 if (!spec->autocfg.line_outs)
5521 return 0; /* can't find valid BIOS pin config */
5522
5523 err = alc861_auto_fill_dac_nids(codec);
5524 if (err < 0)
5525 return err;
5526 err = alc_auto_add_multi_channel_mode(codec, alc861_auto_fill_dac_nids);
5527 if (err < 0)
5528 return err;
5529 err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
5530 if (err < 0)
5531 return err;
5532 err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
5533 if (err < 0)
5534 return err;
5535 err = alc_auto_create_input_ctls(codec);
5536 if (err < 0)
5537 return err;
5538
5539 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5540
5541 alc_auto_parse_digital(codec);
5542
5543 if (spec->kctls.list)
5544 add_mixer(spec, spec->kctls.list);
5545
5546 alc_remove_invalid_adc_nids(codec);
5547
5548 alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
5549 alc_auto_check_switches(codec);
5550
5551 set_capture_mixer(codec);
5552
5553 return 1;
5554}
5555
5556/* additional initialization for auto-configuration model */
5557static void alc861_auto_init(struct hda_codec *codec)
5558{
5559 struct alc_spec *spec = codec->spec;
5560 alc861_auto_init_multi_out(codec);
5561 alc861_auto_init_hp_out(codec);
5562 alc_auto_init_analog_input(codec);
5563 alc_auto_init_digital(codec);
5564 if (spec->unsol_event)
5565 alc_inithook(codec);
5566}
5567
5568#ifdef CONFIG_SND_HDA_POWER_SAVE
5569static const struct hda_amp_list alc861_loopbacks[] = {
5570 { 0x15, HDA_INPUT, 0 },
5571 { 0x15, HDA_INPUT, 1 },
5572 { 0x15, HDA_INPUT, 2 },
5573 { 0x15, HDA_INPUT, 3 },
5574 { } /* end */
5575};
5576#endif
5577
5578
5579/* Pin config fixes */
5580enum {
5581 PINFIX_FSC_AMILO_PI1505,
5582};
5583
5584static const struct alc_fixup alc861_fixups[] = {
5585 [PINFIX_FSC_AMILO_PI1505] = {
5586 .type = ALC_FIXUP_PINS,
5587 .v.pins = (const struct alc_pincfg[]) {
5588 { 0x0b, 0x0221101f }, /* HP */
5589 { 0x0f, 0x90170310 }, /* speaker */
5590 { }
5591 }
5592 },
5593};
5594
5595static const struct snd_pci_quirk alc861_fixup_tbl[] = {
5596 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
5597 {}
5598};
5599
5600/*
5601 */
5602#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5603#include "alc861_quirks.c"
5604#endif
5605
5606static int patch_alc861(struct hda_codec *codec)
5607{
5608 struct alc_spec *spec;
5609 int board_config;
5610 int err;
5611
5612 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5613 if (spec == NULL)
5614 return -ENOMEM;
5615
5616 codec->spec = spec;
5617
5618 spec->mixer_nid = 0x15;
5619
5620 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
5621 alc861_models, alc861_cfg_tbl);
5622
5623 if (board_config < 0) {
5624 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5625 codec->chip_name);
5626 board_config = ALC_MODEL_AUTO;
5627 }
5628
5629 if (board_config == ALC_MODEL_AUTO) {
5630 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
5631 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5632 }
5633
5634 if (board_config == ALC_MODEL_AUTO) {
5635 /* automatic parse from the BIOS config */
5636 err = alc861_parse_auto_config(codec);
5637 if (err < 0) {
5638 alc_free(codec);
5639 return err;
5640 }
5641#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5642 else if (!err) {
5643 printk(KERN_INFO
5644 "hda_codec: Cannot set up configuration "
5645 "from BIOS. Using base mode...\n");
5646 board_config = ALC861_3ST_DIG;
5647 }
5648#endif
5649 }
5650
5651 err = snd_hda_attach_beep_device(codec, 0x23);
5652 if (err < 0) {
5653 alc_free(codec);
5654 return err;
5655 }
5656
5657 if (board_config != ALC_MODEL_AUTO)
5658 setup_preset(codec, &alc861_presets[board_config]);
5659
5660 if (!spec->adc_nids) {
5661 alc_auto_fill_adc_caps(codec);
5662 alc_rebuild_imux_for_auto_mic(codec);
5663 alc_remove_invalid_adc_nids(codec);
5664 }
5665
5666 if (!spec->cap_mixer)
5667 set_capture_mixer(codec);
5668 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
5669
5670 spec->vmaster_nid = 0x03;
5671
5672 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5673
5674 codec->patch_ops = alc_patch_ops;
5675 if (board_config == ALC_MODEL_AUTO) {
5676 spec->init_hook = alc861_auto_init;
5677#ifdef CONFIG_SND_HDA_POWER_SAVE
5678 spec->power_hook = alc_power_eapd;
5679#endif
5680 }
5681#ifdef CONFIG_SND_HDA_POWER_SAVE
5682 if (!spec->loopback.amplist)
5683 spec->loopback.amplist = alc861_loopbacks;
5684#endif
5685
5686 return 0;
5687}
5688
5689/*
5690 * ALC861-VD support
5691 *
5692 * Based on ALC882
5693 *
5694 * In addition, an independent DAC
5695 */
5696#ifdef CONFIG_SND_HDA_POWER_SAVE
5697#define alc861vd_loopbacks alc880_loopbacks
5698#endif
5699
5700/*
5701 * BIOS auto configuration
5702 */
5703#define alc861vd_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
5704#define alc861vd_fixed_pin_idx(nid) ((nid) - 0x14)
5705#define alc861vd_is_multi_pin(nid) ((nid) >= 0x18)
5706#define alc861vd_multi_pin_idx(nid) ((nid) - 0x18)
5707#define alc861vd_idx_to_dac(nid) ((nid) + 0x02)
5708#define alc861vd_dac_to_idx(nid) ((nid) - 0x02)
5709#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)
5710#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)
5711
5712/* add playback controls from the parsed DAC table */
5713/* Based on ALC880 version. But ALC861VD has separate,
5714 * different NIDs for mute/unmute switch and volume control */
5715static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
5716 const struct auto_pin_cfg *cfg)
5717{
5718 hda_nid_t nid_v, nid_s;
5719 int i, err, noutputs;
5720
5721 noutputs = cfg->line_outs;
5722 if (spec->multi_ios > 0)
5723 noutputs += spec->multi_ios;
5724
5725 for (i = 0; i < noutputs; i++) {
5726 const char *name;
5727 int index;
5728 if (!spec->multiout.dac_nids[i])
5729 continue;
5730 nid_v = alc861vd_idx_to_mixer_vol(
5731 alc861vd_dac_to_idx(
5732 spec->multiout.dac_nids[i]));
5733 nid_s = alc861vd_idx_to_mixer_switch(
5734 alc861vd_dac_to_idx(
5735 spec->multiout.dac_nids[i]));
5736
5737 name = alc_get_line_out_pfx(spec, i, true, &index);
5738 if (!name) {
5739 /* Center/LFE */
5740 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5741 "Center",
5742 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
5743 HDA_OUTPUT));
5744 if (err < 0)
5745 return err;
5746 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5747 "LFE",
5748 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
5749 HDA_OUTPUT));
5750 if (err < 0)
5751 return err;
5752 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5753 "Center",
5754 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
5755 HDA_INPUT));
5756 if (err < 0)
5757 return err;
5758 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5759 "LFE",
5760 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
5761 HDA_INPUT));
5762 if (err < 0)
5763 return err;
5764 } else {
5765 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
5766 name, index,
5767 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
5768 HDA_OUTPUT));
5769 if (err < 0)
5770 return err;
5771 err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
5772 name, index,
5773 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
5774 HDA_INPUT));
5775 if (err < 0)
5776 return err;
5777 }
5778 }
5779 return 0;
5780}
5781
5782/* add playback controls for speaker and HP outputs */
5783/* Based on ALC880 version. But ALC861VD has separate,
5784 * different NIDs for mute/unmute switch and volume control */
5785static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
5786 hda_nid_t pin, const char *pfx)
5787{
5788 hda_nid_t nid_v, nid_s;
5789 int err;
5790
5791 if (!pin)
5792 return 0;
5793
5794 if (alc861vd_is_fixed_pin(pin)) {
5795 nid_v = alc861vd_idx_to_dac(alc861vd_fixed_pin_idx(pin));
5796 /* specify the DAC as the extra output */
5797 if (!spec->multiout.hp_nid)
5798 spec->multiout.hp_nid = nid_v;
5799 else
5800 spec->multiout.extra_out_nid[0] = nid_v;
5801 /* control HP volume/switch on the output mixer amp */
5802 nid_v = alc861vd_idx_to_mixer_vol(
5803 alc861vd_fixed_pin_idx(pin));
5804 nid_s = alc861vd_idx_to_mixer_switch(
5805 alc861vd_fixed_pin_idx(pin));
5806
5807 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
5808 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
5809 if (err < 0)
5810 return err;
5811 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
5812 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
5813 if (err < 0)
5814 return err;
5815 } else if (alc861vd_is_multi_pin(pin)) {
5816 /* set manual connection */
5817 /* we have only a switch on HP-out PIN */
5818 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
5819 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
5820 if (err < 0)
5821 return err;
5822 }
5823 return 0;
5824}
5825
5826/* parse the BIOS configuration and set up the alc_spec
5827 * return 1 if successful, 0 if the proper config is not found,
5828 * or a negative error code
5829 * Based on ALC880 version - had to change it to override
5830 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
5831static int alc861vd_parse_auto_config(struct hda_codec *codec)
5832{
5833 struct alc_spec *spec = codec->spec;
5834 int err;
5835 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
5836
5837 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5838 alc861vd_ignore);
5839 if (err < 0)
5840 return err;
5841 if (!spec->autocfg.line_outs)
5842 return 0; /* can't find valid BIOS pin config */
5843
5844 err = alc_auto_fill_dac_nids(codec);
5845 if (err < 0)
5846 return err;
5847 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
5848 if (err < 0)
5849 return err;
5850 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
5851 if (err < 0)
5852 return err;
5853 err = alc861vd_auto_create_extra_out(spec,
5854 spec->autocfg.speaker_pins[0],
5855 "Speaker");
5856 if (err < 0)
5857 return err;
5858 err = alc861vd_auto_create_extra_out(spec,
5859 spec->autocfg.hp_pins[0],
5860 "Headphone");
5861 if (err < 0)
5862 return err;
5863 err = alc_auto_create_input_ctls(codec);
5864 if (err < 0)
5865 return err;
5866
5867 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5868
5869 alc_auto_parse_digital(codec);
5870
5871 if (spec->kctls.list)
5872 add_mixer(spec, spec->kctls.list);
5873
5874 alc_remove_invalid_adc_nids(codec);
5875
5876 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
5877 alc_auto_check_switches(codec);
5878
5879 err = alc_auto_add_mic_boost(codec);
5880 if (err < 0)
5881 return err;
5882
5883 return 1;
5884}
5885
5886/* additional initialization for auto-configuration model */
5887static void alc861vd_auto_init(struct hda_codec *codec)
5888{
5889 struct alc_spec *spec = codec->spec;
5890 alc_auto_init_multi_out(codec);
5891 alc_auto_init_extra_out(codec);
5892 alc_auto_init_analog_input(codec);
5893 alc_auto_init_input_src(codec);
5894 alc_auto_init_digital(codec);
5895 if (spec->unsol_event)
5896 alc_inithook(codec);
5897}
5898
5899enum {
5900 ALC660VD_FIX_ASUS_GPIO1
5901};
5902
5903/* reset GPIO1 */
5904static const struct alc_fixup alc861vd_fixups[] = {
5905 [ALC660VD_FIX_ASUS_GPIO1] = {
5906 .type = ALC_FIXUP_VERBS,
5907 .v.verbs = (const struct hda_verb[]) {
5908 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5909 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5910 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5911 { }
5912 }
5913 },
5914};
5915
5916static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
5917 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
5918 {}
5919};
5920
5921static const struct hda_verb alc660vd_eapd_verbs[] = {
5922 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
5923 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
5924 { }
5925};
5926
5927/*
5928 */
5929#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5930#include "alc861vd_quirks.c"
5931#endif
5932
5933static int patch_alc861vd(struct hda_codec *codec)
5934{
5935 struct alc_spec *spec;
5936 int err, board_config;
5937
5938 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5939 if (spec == NULL)
5940 return -ENOMEM;
5941
5942 codec->spec = spec;
5943
5944 spec->mixer_nid = 0x0b;
5945
5946 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
5947 alc861vd_models, alc861vd_cfg_tbl);
5948
5949 if (board_config < 0) {
5950 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5951 codec->chip_name);
5952 board_config = ALC_MODEL_AUTO;
5953 }
5954
5955 if (board_config == ALC_MODEL_AUTO) {
5956 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
5957 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5958 }
5959
5960 if (board_config == ALC_MODEL_AUTO) {
5961 /* automatic parse from the BIOS config */
5962 err = alc861vd_parse_auto_config(codec);
5963 if (err < 0) {
5964 alc_free(codec);
5965 return err;
5966 }
5967#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5968 else if (!err) {
5969 printk(KERN_INFO
5970 "hda_codec: Cannot set up configuration "
5971 "from BIOS. Using base mode...\n");
5972 board_config = ALC861VD_3ST;
5973 }
5974#endif
5975 }
5976
5977 err = snd_hda_attach_beep_device(codec, 0x23);
5978 if (err < 0) {
5979 alc_free(codec);
5980 return err;
5981 }
5982
5983 if (board_config != ALC_MODEL_AUTO)
5984 setup_preset(codec, &alc861vd_presets[board_config]);
5985
5986 if (codec->vendor_id == 0x10ec0660) {
5987 /* always turn on EAPD */
5988 add_verb(spec, alc660vd_eapd_verbs);
5989 }
5990
5991 if (!spec->adc_nids) {
5992 alc_auto_fill_adc_caps(codec);
5993 alc_rebuild_imux_for_auto_mic(codec);
5994 alc_remove_invalid_adc_nids(codec);
5995 }
5996
5997 set_capture_mixer(codec);
5998 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5999
6000 spec->vmaster_nid = 0x02;
6001
6002 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
6003
6004 codec->patch_ops = alc_patch_ops;
6005
6006 if (board_config == ALC_MODEL_AUTO)
6007 spec->init_hook = alc861vd_auto_init;
6008 spec->shutup = alc_eapd_shutup;
6009#ifdef CONFIG_SND_HDA_POWER_SAVE
6010 if (!spec->loopback.amplist)
6011 spec->loopback.amplist = alc861vd_loopbacks;
6012#endif
6013
6014 return 0;
6015}
6016
6017/*
6018 * ALC662 support
6019 *
6020 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
6021 * configuration. Each pin widget can choose any input DACs and a mixer.
6022 * Each ADC is connected from a mixer of all inputs. This makes possible
6023 * 6-channel independent captures.
6024 *
6025 * In addition, an independent DAC for the multi-playback (not used in this
6026 * driver yet).
6027 */
6028#ifdef CONFIG_SND_HDA_POWER_SAVE
6029#define alc662_loopbacks alc880_loopbacks
6030#endif
6031
6032/*
6033 * BIOS auto configuration
6034 */
6035
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006036static int alc662_parse_auto_config(struct hda_codec *codec)
6037{
6038 struct alc_spec *spec = codec->spec;
6039 int err;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02006040 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006041
6042 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
6043 alc662_ignore);
6044 if (err < 0)
6045 return err;
6046 if (!spec->autocfg.line_outs)
6047 return 0; /* can't find valid BIOS pin config */
6048
Takashi Iwai343a04b2011-07-06 14:28:39 +02006049 err = alc_auto_fill_dac_nids(codec);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006050 if (err < 0)
6051 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02006052 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
Takashi Iwaice764ab2011-04-27 16:35:23 +02006053 if (err < 0)
6054 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02006055 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006056 if (err < 0)
6057 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02006058 err = alc_auto_create_extra_out(codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006059 spec->autocfg.speaker_pins[0],
Takashi Iwai3af9ee62011-06-27 12:34:01 +02006060 spec->multiout.extra_out_nid[0],
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006061 "Speaker");
6062 if (err < 0)
6063 return err;
Takashi Iwai343a04b2011-07-06 14:28:39 +02006064 err = alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
Takashi Iwai3af9ee62011-06-27 12:34:01 +02006065 spec->multiout.hp_nid,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006066 "Headphone");
6067 if (err < 0)
6068 return err;
Takashi Iwaib7821702011-07-06 15:12:46 +02006069 err = alc_auto_create_input_ctls(codec);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006070 if (err < 0)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006071 return err;
6072
6073 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
6074
Takashi Iwai757899a2010-07-30 10:48:14 +02006075 alc_auto_parse_digital(codec);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006076
Takashi Iwai603c4012008-07-30 15:01:44 +02006077 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +01006078 add_mixer(spec, spec->kctls.list);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006079
Takashi Iwai21268962011-07-07 15:01:13 +02006080 alc_remove_invalid_adc_nids(codec);
Takashi Iwaiee979a142008-09-02 15:42:20 +02006081
Kailang Yang6227cdc2010-02-25 08:36:52 +01006082 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
6083 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
6084 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
6085 else
6086 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai21268962011-07-07 15:01:13 +02006087 alc_auto_check_switches(codec);
6088
6089 err = alc_auto_add_mic_boost(codec);
6090 if (err < 0)
6091 return err;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02006092
Takashi Iwai8c872862007-06-19 12:11:16 +02006093 return 1;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006094}
6095
6096/* additional initialization for auto-configuration model */
6097static void alc662_auto_init(struct hda_codec *codec)
6098{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006099 struct alc_spec *spec = codec->spec;
Takashi Iwai343a04b2011-07-06 14:28:39 +02006100 alc_auto_init_multi_out(codec);
6101 alc_auto_init_extra_out(codec);
Takashi Iwai0a7f5322011-07-06 15:15:12 +02006102 alc_auto_init_analog_input(codec);
Takashi Iwaif970de22011-07-06 17:39:59 +02006103 alc_auto_init_input_src(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +02006104 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006105 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +02006106 alc_inithook(codec);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006107}
6108
Todd Broch6be79482010-12-07 16:51:05 -08006109static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006110 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01006111{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006112 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01006113 return;
Todd Broch6be79482010-12-07 16:51:05 -08006114 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
6115 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
6116 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
6117 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
6118 (0 << AC_AMPCAP_MUTE_SHIFT)))
6119 printk(KERN_WARNING
6120 "hda_codec: failed to override amp caps for NID 0x2\n");
6121}
6122
David Henningsson6cb3b702010-09-09 08:51:44 +02006123enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04006124 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02006125 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08006126 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01006127 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02006128 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006129 ALC662_FIXUP_HP_RP5800,
David Henningsson6cb3b702010-09-09 08:51:44 +02006130};
6131
6132static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04006133 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006134 .type = ALC_FIXUP_PINS,
6135 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04006136 { 0x15, 0x99130112 }, /* subwoofer */
6137 { }
6138 }
6139 },
David Henningsson6cb3b702010-09-09 08:51:44 +02006140 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006141 .type = ALC_FIXUP_PINS,
6142 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02006143 { 0x17, 0x99130112 }, /* subwoofer */
6144 { }
6145 }
6146 },
Todd Broch6be79482010-12-07 16:51:05 -08006147 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006148 .type = ALC_FIXUP_FUNC,
6149 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01006150 },
6151 [ALC662_FIXUP_CZC_P10T] = {
6152 .type = ALC_FIXUP_VERBS,
6153 .v.verbs = (const struct hda_verb[]) {
6154 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
6155 {}
6156 }
6157 },
David Henningsson94024cd2011-04-29 14:10:55 +02006158 [ALC662_FIXUP_SKU_IGNORE] = {
6159 .type = ALC_FIXUP_SKU,
6160 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02006161 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006162 [ALC662_FIXUP_HP_RP5800] = {
6163 .type = ALC_FIXUP_PINS,
6164 .v.pins = (const struct alc_pincfg[]) {
6165 { 0x14, 0x0221201f }, /* HP out */
6166 { }
6167 },
6168 .chained = true,
6169 .chain_id = ALC662_FIXUP_SKU_IGNORE
6170 },
David Henningsson6cb3b702010-09-09 08:51:44 +02006171};
6172
Takashi Iwaia9111322011-05-02 11:30:18 +02006173static const struct snd_pci_quirk alc662_fixup_tbl[] = {
David Henningssona6c47a82011-02-10 15:39:19 +01006174 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02006175 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04006176 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006177 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05006178 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06006179 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02006180 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01006181 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02006182 {}
6183};
6184
Todd Broch6be79482010-12-07 16:51:05 -08006185static const struct alc_model_fixup alc662_fixup_models[] = {
6186 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
6187 {}
6188};
David Henningsson6cb3b702010-09-09 08:51:44 +02006189
6190
Takashi Iwai1d045db2011-07-07 18:23:21 +02006191/*
6192 */
6193#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
6194#include "alc662_quirks.c"
6195#endif
6196
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006197static int patch_alc662(struct hda_codec *codec)
6198{
6199 struct alc_spec *spec;
6200 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02006201 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006202
6203 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6204 if (!spec)
6205 return -ENOMEM;
6206
6207 codec->spec = spec;
6208
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006209 spec->mixer_nid = 0x0b;
6210
Kailang Yangda00c242010-03-19 11:23:45 +01006211 alc_auto_parse_customize_define(codec);
6212
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02006213 alc_fix_pll_init(codec, 0x20, 0x04, 15);
6214
Kailang Yang693194f2010-10-21 08:51:48 +02006215 coef = alc_read_coef_idx(codec, 0);
6216 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01006217 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02006218 else if (coef & (1 << 14) &&
6219 codec->bus->pci->subsystem_vendor == 0x1025 &&
6220 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01006221 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02006222 else if (coef == 0x4011)
6223 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01006224
Takashi Iwai1d045db2011-07-07 18:23:21 +02006225 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
6226 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006227 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02006228 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
6229 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02006230 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006231 }
6232
Takashi Iwai1d045db2011-07-07 18:23:21 +02006233 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006234 alc_pick_fixup(codec, alc662_fixup_models,
6235 alc662_fixup_tbl, alc662_fixups);
6236 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006237 /* automatic parse from the BIOS config */
6238 err = alc662_parse_auto_config(codec);
6239 if (err < 0) {
6240 alc_free(codec);
6241 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006242 }
6243#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
6244 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006245 printk(KERN_INFO
6246 "hda_codec: Cannot set up configuration "
6247 "from BIOS. Using base mode...\n");
6248 board_config = ALC662_3ST_2ch_DIG;
6249 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02006250#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006251 }
6252
Takashi Iwaidc1eae22010-07-29 15:30:02 +02006253 if (has_cdefine_beep(codec)) {
Takashi Iwai8af25912010-07-28 17:37:16 +02006254 err = snd_hda_attach_beep_device(codec, 0x1);
6255 if (err < 0) {
6256 alc_free(codec);
6257 return err;
6258 }
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09006259 }
6260
Takashi Iwai1d045db2011-07-07 18:23:21 +02006261 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02006262 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006263
Takashi Iwaidd704692009-08-11 08:45:11 +02006264 if (!spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02006265 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02006266 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02006267 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02006268 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006269
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006270 if (!spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02006271 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006272
Takashi Iwaidc1eae22010-07-29 15:30:02 +02006273 if (has_cdefine_beep(codec)) {
Kailang Yangda00c242010-03-19 11:23:45 +01006274 switch (codec->vendor_id) {
6275 case 0x10ec0662:
6276 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
6277 break;
6278 case 0x10ec0272:
6279 case 0x10ec0663:
6280 case 0x10ec0665:
6281 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
6282 break;
6283 case 0x10ec0273:
6284 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
6285 break;
6286 }
Kailang Yangcec27c82010-02-04 14:18:18 +01006287 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01006288 spec->vmaster_nid = 0x02;
6289
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006290 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
6291
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006292 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006293 if (board_config == ALC_MODEL_AUTO)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006294 spec->init_hook = alc662_auto_init;
Takashi Iwai1c716152011-04-07 10:37:16 +02006295 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02006296
Kailang Yangbf1b0222010-10-21 08:49:56 +02006297 alc_init_jacks(codec);
6298
Takashi Iwaicb53c622007-08-10 17:21:45 +02006299#ifdef CONFIG_SND_HDA_POWER_SAVE
6300 if (!spec->loopback.amplist)
6301 spec->loopback.amplist = alc662_loopbacks;
6302#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006303
6304 return 0;
6305}
6306
Kailang Yang274693f2009-12-03 10:07:50 +01006307static int patch_alc888(struct hda_codec *codec)
6308{
6309 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
6310 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01006311 if (codec->vendor_id == 0x10ec0887)
6312 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
6313 else
6314 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01006315 if (!codec->chip_name) {
6316 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01006317 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01006318 }
6319 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01006320 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01006321 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01006322}
6323
Kailang Yangb478b992011-05-18 11:51:15 +02006324static int patch_alc899(struct hda_codec *codec)
6325{
6326 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
6327 kfree(codec->chip_name);
6328 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
6329 }
6330 return patch_alc882(codec);
6331}
6332
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006333/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006334 * ALC680 support
6335 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006336/* create input playback/capture controls for the given pin */
6337static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
6338 const char *ctlname, int idx)
6339{
6340 hda_nid_t dac;
6341 int err;
6342
6343 switch (nid) {
6344 case 0x14:
6345 dac = 0x02;
6346 break;
6347 case 0x15:
6348 dac = 0x03;
6349 break;
6350 case 0x16:
6351 dac = 0x04;
6352 break;
6353 default:
6354 return 0;
6355 }
6356 if (spec->multiout.dac_nids[0] != dac &&
6357 spec->multiout.dac_nids[1] != dac) {
6358 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
6359 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
6360 HDA_OUTPUT));
6361 if (err < 0)
6362 return err;
6363
6364 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
6365 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
6366
6367 if (err < 0)
6368 return err;
Takashi Iwaidda14412011-05-02 11:29:30 +02006369 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006370 }
6371
6372 return 0;
6373}
6374
6375/* add playback controls from the parsed DAC table */
6376static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec,
6377 const struct auto_pin_cfg *cfg)
6378{
6379 hda_nid_t nid;
6380 int err;
6381
6382 spec->multiout.dac_nids = spec->private_dac_nids;
6383
6384 nid = cfg->line_out_pins[0];
6385 if (nid) {
6386 const char *name;
Takashi Iwai2e925dd2011-06-24 11:27:22 +02006387 int index;
6388 name = alc_get_line_out_pfx(spec, 0, true, &index);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006389 err = alc680_new_analog_output(spec, nid, name, 0);
6390 if (err < 0)
6391 return err;
6392 }
6393
6394 nid = cfg->speaker_pins[0];
6395 if (nid) {
6396 err = alc680_new_analog_output(spec, nid, "Speaker", 0);
6397 if (err < 0)
6398 return err;
6399 }
6400 nid = cfg->hp_pins[0];
6401 if (nid) {
6402 err = alc680_new_analog_output(spec, nid, "Headphone", 0);
6403 if (err < 0)
6404 return err;
6405 }
6406
6407 return 0;
6408}
6409
6410static void alc680_auto_set_output_and_unmute(struct hda_codec *codec,
6411 hda_nid_t nid, int pin_type)
6412{
6413 alc_set_pin_output(codec, nid, pin_type);
6414}
6415
6416static void alc680_auto_init_multi_out(struct hda_codec *codec)
6417{
6418 struct alc_spec *spec = codec->spec;
6419 hda_nid_t nid = spec->autocfg.line_out_pins[0];
6420 if (nid) {
6421 int pin_type = get_pin_type(spec->autocfg.line_out_type);
6422 alc680_auto_set_output_and_unmute(codec, nid, pin_type);
6423 }
6424}
6425
6426static void alc680_auto_init_hp_out(struct hda_codec *codec)
6427{
6428 struct alc_spec *spec = codec->spec;
6429 hda_nid_t pin;
6430
6431 pin = spec->autocfg.hp_pins[0];
6432 if (pin)
6433 alc680_auto_set_output_and_unmute(codec, pin, PIN_HP);
6434 pin = spec->autocfg.speaker_pins[0];
6435 if (pin)
6436 alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT);
6437}
6438
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006439/*
6440 * BIOS auto configuration
6441 */
6442static int alc680_parse_auto_config(struct hda_codec *codec)
6443{
6444 struct alc_spec *spec = codec->spec;
6445 int err;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02006446 static const hda_nid_t alc680_ignore[] = { 0 };
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006447
6448 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
6449 alc680_ignore);
6450 if (err < 0)
6451 return err;
Kailang Yangc69aefa2010-08-17 10:39:22 +02006452
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006453 if (!spec->autocfg.line_outs) {
6454 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
6455 spec->multiout.max_channels = 2;
6456 spec->no_analog = 1;
6457 goto dig_only;
6458 }
6459 return 0; /* can't find valid BIOS pin config */
6460 }
6461 err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg);
6462 if (err < 0)
6463 return err;
6464
Takashi Iwai21268962011-07-07 15:01:13 +02006465 err = alc_auto_create_input_ctls(codec);
6466 if (err < 0)
6467 return err;
6468
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006469 spec->multiout.max_channels = 2;
6470
6471 dig_only:
6472 /* digital only support output */
Takashi Iwai757899a2010-07-30 10:48:14 +02006473 alc_auto_parse_digital(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006474 if (spec->kctls.list)
6475 add_mixer(spec, spec->kctls.list);
6476
Takashi Iwai21268962011-07-07 15:01:13 +02006477 alc_remove_invalid_adc_nids(codec);
6478
6479 alc_auto_check_switches(codec);
6480
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006481 err = alc_auto_add_mic_boost(codec);
6482 if (err < 0)
6483 return err;
6484
6485 return 1;
6486}
6487
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006488/* init callback for auto-configuration model -- overriding the default init */
6489static void alc680_auto_init(struct hda_codec *codec)
6490{
6491 struct alc_spec *spec = codec->spec;
6492 alc680_auto_init_multi_out(codec);
6493 alc680_auto_init_hp_out(codec);
Takashi Iwai0a7f5322011-07-06 15:15:12 +02006494 alc_auto_init_analog_input(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02006495 alc_auto_init_input_src(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +02006496 alc_auto_init_digital(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006497 if (spec->unsol_event)
6498 alc_inithook(codec);
6499}
6500
6501/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006502 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02006503#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
6504#include "alc680_quirks.c"
6505#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006506
6507static int patch_alc680(struct hda_codec *codec)
6508{
6509 struct alc_spec *spec;
6510 int board_config;
6511 int err;
6512
6513 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6514 if (spec == NULL)
6515 return -ENOMEM;
6516
6517 codec->spec = spec;
6518
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006519 /* ALC680 has no aa-loopback mixer */
6520
Takashi Iwai1d045db2011-07-07 18:23:21 +02006521 board_config = alc_board_config(codec, ALC680_MODEL_LAST,
6522 alc680_models, alc680_cfg_tbl);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006523
Takashi Iwai1d045db2011-07-07 18:23:21 +02006524 if (board_config < 0) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006525 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
6526 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02006527 board_config = ALC_MODEL_AUTO;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006528 }
6529
Takashi Iwai1d045db2011-07-07 18:23:21 +02006530 if (board_config == ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006531 /* automatic parse from the BIOS config */
6532 err = alc680_parse_auto_config(codec);
6533 if (err < 0) {
6534 alc_free(codec);
6535 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006536 }
6537#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
6538 else if (!err) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006539 printk(KERN_INFO
6540 "hda_codec: Cannot set up configuration "
6541 "from BIOS. Using base mode...\n");
6542 board_config = ALC680_BASE;
6543 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02006544#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006545 }
6546
Takashi Iwai1d045db2011-07-07 18:23:21 +02006547 if (board_config != ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006548 setup_preset(codec, &alc680_presets[board_config]);
Takashi Iwai1d045db2011-07-07 18:23:21 +02006549#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
Takashi Iwai21268962011-07-07 15:01:13 +02006550 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006551#endif
Takashi Iwai21268962011-07-07 15:01:13 +02006552 }
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006553
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006554 if (!spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02006555 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02006556 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02006557 alc_remove_invalid_adc_nids(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006558 }
6559
6560 if (!spec->cap_mixer)
6561 set_capture_mixer(codec);
6562
6563 spec->vmaster_nid = 0x02;
6564
6565 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006566 if (board_config == ALC_MODEL_AUTO)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006567 spec->init_hook = alc680_auto_init;
6568
6569 return 0;
6570}
6571
6572/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006573 * patch entries
6574 */
Takashi Iwaia9111322011-05-02 11:30:18 +02006575static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02006576 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006577 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006578 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01006579 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02006580 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01006581 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01006582 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02006583 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01006584 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02006585 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006586 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006587 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006588 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
6589 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
6590 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006591 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +02006592 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006593 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
6594 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02006595 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01006596 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01006597 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006598 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006599 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006600 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +02006601 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02006602 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02006603 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02006604 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02006605 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006606 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01006607 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02006608 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +02006609 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01006610 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai49535502009-06-30 15:28:30 +02006611 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01006612 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02006613 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006614 {} /* terminator */
6615};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01006616
6617MODULE_ALIAS("snd-hda-codec-id:10ec*");
6618
6619MODULE_LICENSE("GPL");
6620MODULE_DESCRIPTION("Realtek HD-audio codec");
6621
6622static struct hda_codec_preset_list realtek_list = {
6623 .preset = snd_hda_preset_realtek,
6624 .owner = THIS_MODULE,
6625};
6626
6627static int __init patch_realtek_init(void)
6628{
6629 return snd_hda_add_codec_preset(&realtek_list);
6630}
6631
6632static void __exit patch_realtek_exit(void)
6633{
6634 snd_hda_delete_codec_preset(&realtek_list);
6635}
6636
6637module_init(patch_realtek_init)
6638module_exit(patch_realtek_exit)