blob: fcb11af9ad24f76a489f35472933238075b7bad5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
Takashi Iwai1d045db2011-07-07 18:23:21 +02004 * HD audio interface patch for Realtek ALC codecs
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Kailang Yangdf694da2005-12-05 19:42:22 +01006 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Takashi Iwai <tiwai@suse.de>
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01009 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020031#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "hda_codec.h"
33#include "hda_local.h"
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090034#include "hda_beep.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Takashi Iwai1d045db2011-07-07 18:23:21 +020036/* unsol event tags */
37#define ALC_FRONT_EVENT 0x01
38#define ALC_DCVOL_EVENT 0x02
39#define ALC_HP_EVENT 0x04
40#define ALC_MIC_EVENT 0x08
Takashi Iwaid4a86d82010-06-23 17:51:26 +020041
Kailang Yangdf694da2005-12-05 19:42:22 +010042/* for GPIO Poll */
43#define GPIO_MASK 0x03
44
Takashi Iwai4a79ba32009-04-22 16:31:35 +020045/* extra amp-initialization sequence types */
46enum {
47 ALC_INIT_NONE,
48 ALC_INIT_DEFAULT,
49 ALC_INIT_GPIO1,
50 ALC_INIT_GPIO2,
51 ALC_INIT_GPIO3,
52};
53
Kailang Yangda00c242010-03-19 11:23:45 +010054struct alc_customize_define {
55 unsigned int sku_cfg;
56 unsigned char port_connectivity;
57 unsigned char check_sum;
58 unsigned char customization;
59 unsigned char external_amp;
60 unsigned int enable_pcbeep:1;
61 unsigned int platform_type:1;
62 unsigned int swap:1;
63 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020064 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010065};
66
Takashi Iwaib5bfbc62011-01-13 14:22:32 +010067struct alc_fixup;
68
Takashi Iwaice764ab2011-04-27 16:35:23 +020069struct alc_multi_io {
70 hda_nid_t pin; /* multi-io widget pin NID */
71 hda_nid_t dac; /* DAC to be connected */
72 unsigned int ctl_in; /* cached input-pin control value */
73};
74
Takashi Iwaid922b512011-04-28 12:18:53 +020075enum {
Takashi Iwai3b8510c2011-04-28 14:03:24 +020076 ALC_AUTOMUTE_PIN, /* change the pin control */
77 ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
78 ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
Takashi Iwaid922b512011-04-28 12:18:53 +020079};
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081struct alc_spec {
82 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020083 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 unsigned int num_mixers;
Takashi Iwaia9111322011-05-02 11:30:18 +020085 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010086 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwai2d9c6482009-10-13 08:06:55 +020088 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +020089 * don't forget NULL
90 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +020091 */
92 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Takashi Iwaiaa563af2009-07-31 10:05:11 +020094 char stream_name_analog[32]; /* analog PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +020095 const struct hda_pcm_stream *stream_analog_playback;
96 const struct hda_pcm_stream *stream_analog_capture;
97 const struct hda_pcm_stream *stream_analog_alt_playback;
98 const struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200100 char stream_name_digital[32]; /* digital PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +0200101 const struct hda_pcm_stream *stream_digital_playback;
102 const struct hda_pcm_stream *stream_digital_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200105 struct hda_multi_out multiout; /* playback set-up
106 * max_channels, dacs must be set
107 * dig_out_nid and hp_nid are optional
108 */
Takashi Iwai63300792008-01-24 15:31:36 +0100109 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100110 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100111 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 /* capture */
114 unsigned int num_adc_nids;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +0200115 const hda_nid_t *adc_nids;
116 const hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200117 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Takashi Iwai1f0f4b82011-06-27 10:52:59 +0200118 hda_nid_t mixer_nid; /* analog-mixer NID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Takashi Iwai840b64c2010-07-13 22:49:01 +0200120 /* capture setup for dynamic dual-adc switch */
Takashi Iwai840b64c2010-07-13 22:49:01 +0200121 hda_nid_t cur_adc;
122 unsigned int cur_adc_stream_tag;
123 unsigned int cur_adc_format;
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200126 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 const struct hda_input_mux *input_mux;
128 unsigned int cur_mux[3];
Takashi Iwai21268962011-07-07 15:01:13 +0200129 hda_nid_t ext_mic_pin;
130 hda_nid_t dock_mic_pin;
131 hda_nid_t int_mic_pin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100134 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200136 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200137 int const_channel_count;
138 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100141 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200142
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200143 /* dynamic controls, init_verbs and input_mux */
144 struct auto_pin_cfg autocfg;
Kailang Yangda00c242010-03-19 11:23:45 +0100145 struct alc_customize_define cdefine;
Takashi Iwai603c4012008-07-30 15:01:44 +0200146 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200147 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200148 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai49535502009-06-30 15:28:30 +0200149 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
150 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai21268962011-07-07 15:01:13 +0200151 hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
152 unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
153 int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
Takashi Iwai834be882006-03-01 14:16:17 +0100154
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100155 /* hooks */
156 void (*init_hook)(struct hda_codec *codec);
157 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100158#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500159 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100160#endif
Takashi Iwai1c716152011-04-07 10:37:16 +0200161 void (*shutup)(struct hda_codec *codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100162
Takashi Iwai834be882006-03-01 14:16:17 +0100163 /* for pin sensing */
Takashi Iwai834be882006-03-01 14:16:17 +0100164 unsigned int jack_present: 1;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200165 unsigned int line_jack_present:1;
Takashi Iwaie9427962011-04-28 15:46:07 +0200166 unsigned int master_mute:1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200167 unsigned int auto_mic:1;
Takashi Iwai21268962011-07-07 15:01:13 +0200168 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
Takashi Iwaid922b512011-04-28 12:18:53 +0200169 unsigned int automute:1; /* HP automute enabled */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200170 unsigned int detect_line:1; /* Line-out detection enabled */
171 unsigned int automute_lines:1; /* automute line-out as well */
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200172 unsigned int automute_hp_lo:1; /* both HP and LO available */
Takashi Iwaicb53c622007-08-10 17:21:45 +0200173
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100174 /* other flags */
175 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai21268962011-07-07 15:01:13 +0200176 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai584c0c42011-03-10 12:51:11 +0100177 unsigned int single_input_src:1;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +0200178 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
Takashi Iwaid922b512011-04-28 12:18:53 +0200179
180 /* auto-mute control */
181 int automute_mode;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200182 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
Takashi Iwaid922b512011-04-28 12:18:53 +0200183
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200184 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200185 int codec_variant; /* flag for other variants */
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100186
Takashi Iwai2134ea42008-01-10 16:53:55 +0100187 /* for virtual master */
188 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200189#ifdef CONFIG_SND_HDA_POWER_SAVE
190 struct hda_loopback_check loopback;
191#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200192
193 /* for PLL fix */
194 hda_nid_t pll_nid;
195 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +0100196
197 /* fix-up list */
198 int fixup_id;
199 const struct alc_fixup *fixup_list;
200 const char *fixup_name;
Takashi Iwaice764ab2011-04-27 16:35:23 +0200201
202 /* multi-io */
203 int multi_ios;
204 struct alc_multi_io multi_io[4];
Kailang Yangdf694da2005-12-05 19:42:22 +0100205};
206
Takashi Iwai1d045db2011-07-07 18:23:21 +0200207#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Takashi Iwai44c02402011-07-08 15:14:19 +0200209static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
210 int dir, unsigned int bits)
211{
212 if (!nid)
213 return false;
214 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
215 if (query_amp_caps(codec, nid, dir) & bits)
216 return true;
217 return false;
218}
219
220#define nid_has_mute(codec, nid, dir) \
221 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
222#define nid_has_volume(codec, nid, dir) \
223 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225/*
226 * input MUX handling
227 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200228static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
229 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230{
231 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
232 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200233 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
234 if (mux_idx >= spec->num_mux_defs)
235 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100236 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
237 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200238 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200241static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
244 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
245 struct alc_spec *spec = codec->spec;
246 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
247
248 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
249 return 0;
250}
251
Takashi Iwai21268962011-07-07 15:01:13 +0200252static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253{
Takashi Iwai21268962011-07-07 15:01:13 +0200254 struct alc_spec *spec = codec->spec;
255 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
256
257 if (spec->cur_adc && spec->cur_adc != new_adc) {
258 /* stream is running, let's swap the current ADC */
259 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
260 spec->cur_adc = new_adc;
261 snd_hda_codec_setup_stream(codec, new_adc,
262 spec->cur_adc_stream_tag, 0,
263 spec->cur_adc_format);
264 return true;
265 }
266 return false;
267}
268
269/* select the given imux item; either unmute exclusively or select the route */
270static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
271 unsigned int idx, bool force)
272{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100274 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100275 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200276 int i, type;
277 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Takashi Iwaicd896c32008-11-18 12:36:33 +0100279 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
280 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100281 if (!imux->num_items && mux_idx > 0)
282 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100283
Takashi Iwai21268962011-07-07 15:01:13 +0200284 if (idx >= imux->num_items)
285 idx = imux->num_items - 1;
286 if (spec->cur_mux[adc_idx] == idx && !force)
287 return 0;
288 spec->cur_mux[adc_idx] = idx;
289
290 if (spec->dyn_adc_switch) {
291 alc_dyn_adc_pcm_resetup(codec, idx);
292 adc_idx = spec->dyn_adc_idx[idx];
293 }
294
295 nid = spec->capsrc_nids ?
296 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
297
298 /* no selection? */
299 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
300 return 1;
301
Takashi Iwaia22d5432009-07-27 12:54:26 +0200302 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200303 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100304 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100305 for (i = 0; i < imux->num_items; i++) {
306 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
307 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
308 imux->items[i].index,
309 HDA_AMP_MUTE, v);
310 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100311 } else {
312 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200313 snd_hda_codec_write_cache(codec, nid, 0,
314 AC_VERB_SET_CONNECT_SEL,
315 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100316 }
Takashi Iwai21268962011-07-07 15:01:13 +0200317 return 1;
318}
319
320static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
321 struct snd_ctl_elem_value *ucontrol)
322{
323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
324 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
325 return alc_mux_select(codec, adc_idx,
326 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100327}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100330 * set up the input pin config (depending on the given auto-pin type)
331 */
332static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
333 int auto_pin_type)
334{
335 unsigned int val = PIN_IN;
336
Takashi Iwai86e29592010-09-09 14:50:17 +0200337 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100338 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200339 unsigned int oldval;
340 oldval = snd_hda_codec_read(codec, nid, 0,
341 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100342 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100343 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200344 /* if the default pin setup is vref50, we give it priority */
345 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100346 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200347 else if (pincap & AC_PINCAP_VREF_50)
348 val = PIN_VREF50;
349 else if (pincap & AC_PINCAP_VREF_100)
350 val = PIN_VREF100;
351 else if (pincap & AC_PINCAP_VREF_GRD)
352 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100353 }
354 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
355}
356
357/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200358 * Append the given mixer and verb elements for the later use
359 * The mixer array is referred in build_controls(), and init_verbs are
360 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100361 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200362static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100363{
364 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
365 return;
366 spec->mixers[spec->num_mixers++] = mix;
367}
368
369static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
370{
371 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
372 return;
373 spec->init_verbs[spec->num_init_verbs++] = verb;
374}
375
376/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200377 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100378 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200379/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200380static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200381 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
382 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
383 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
384 { }
385};
386
Takashi Iwaia9111322011-05-02 11:30:18 +0200387static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200388 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
389 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
390 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
391 { }
392};
393
Takashi Iwaia9111322011-05-02 11:30:18 +0200394static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200395 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
396 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
397 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
398 { }
399};
400
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200401/*
402 * Fix hardware PLL issue
403 * On some codecs, the analog PLL gating control must be off while
404 * the default value is 1.
405 */
406static void alc_fix_pll(struct hda_codec *codec)
407{
408 struct alc_spec *spec = codec->spec;
409 unsigned int val;
410
411 if (!spec->pll_nid)
412 return;
413 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
414 spec->pll_coef_idx);
415 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
416 AC_VERB_GET_PROC_COEF, 0);
417 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
418 spec->pll_coef_idx);
419 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
420 val & ~(1 << spec->pll_coef_bit));
421}
422
423static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
424 unsigned int coef_idx, unsigned int coef_bit)
425{
426 struct alc_spec *spec = codec->spec;
427 spec->pll_nid = nid;
428 spec->pll_coef_idx = coef_idx;
429 spec->pll_coef_bit = coef_bit;
430 alc_fix_pll(codec);
431}
432
Takashi Iwai1d045db2011-07-07 18:23:21 +0200433/*
434 * Jack-reporting via input-jack layer
435 */
436
437/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200438static int alc_init_jacks(struct hda_codec *codec)
439{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100440#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200441 struct alc_spec *spec = codec->spec;
442 int err;
443 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200444 unsigned int mic_nid = spec->ext_mic_pin;
445 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200446
Takashi Iwai265a0242010-09-21 11:26:21 +0200447 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100448 err = snd_hda_input_jack_add(codec, hp_nid,
449 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200450 if (err < 0)
451 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100452 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200453 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200454
Takashi Iwai265a0242010-09-21 11:26:21 +0200455 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100456 err = snd_hda_input_jack_add(codec, mic_nid,
457 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200458 if (err < 0)
459 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100460 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200461 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200462 if (dock_nid) {
463 err = snd_hda_input_jack_add(codec, dock_nid,
464 SND_JACK_MICROPHONE, NULL);
465 if (err < 0)
466 return err;
467 snd_hda_input_jack_report(codec, dock_nid);
468 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100469#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200470 return 0;
471}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200472
Takashi Iwai1d045db2011-07-07 18:23:21 +0200473/*
474 * Jack detections for HP auto-mute and mic-switch
475 */
476
477/* check each pin in the given array; returns true if any of them is plugged */
478static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200479{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200480 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200481
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200482 for (i = 0; i < num_pins; i++) {
483 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200484 if (!nid)
485 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100486 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200487 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200488 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200489 return present;
490}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200491
Takashi Iwai1d045db2011-07-07 18:23:21 +0200492/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200493static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200494 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200495{
496 struct alc_spec *spec = codec->spec;
497 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200498 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200499 int i;
500
501 for (i = 0; i < num_pins; i++) {
502 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200503 if (!nid)
504 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200505 switch (spec->automute_mode) {
506 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200507 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200508 AC_VERB_SET_PIN_WIDGET_CONTROL,
509 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200510 break;
511 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200512 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200513 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200514 break;
515 case ALC_AUTOMUTE_MIXER:
516 nid = spec->automute_mixer_nid[i];
517 if (!nid)
518 break;
519 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200520 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200521 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200522 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200523 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200524 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200525 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200526}
527
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200528/* Toggle internal speakers muting */
529static void update_speakers(struct hda_codec *codec)
530{
531 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200532 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200533
Takashi Iwaic0a20262011-06-10 15:28:15 +0200534 /* Control HP pins/amps depending on master_mute state;
535 * in general, HP pins/amps control should be enabled in all cases,
536 * but currently set only for master_mute, just to be safe
537 */
538 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
539 spec->autocfg.hp_pins, spec->master_mute, true);
540
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200541 if (!spec->automute)
542 on = 0;
543 else
544 on = spec->jack_present | spec->line_jack_present;
545 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200546 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200547 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200548
549 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200550 /* if LO is a copy of either HP or Speaker, don't need to handle it */
551 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
552 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200553 return;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200554 if (!spec->automute_lines || !spec->automute)
555 on = 0;
556 else
557 on = spec->jack_present;
558 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200559 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200560 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200561}
562
Takashi Iwai1d045db2011-07-07 18:23:21 +0200563/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200564static void alc_hp_automute(struct hda_codec *codec)
565{
566 struct alc_spec *spec = codec->spec;
567
568 if (!spec->automute)
569 return;
570 spec->jack_present =
571 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
572 spec->autocfg.hp_pins);
573 update_speakers(codec);
574}
575
Takashi Iwai1d045db2011-07-07 18:23:21 +0200576/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200577static void alc_line_automute(struct hda_codec *codec)
578{
579 struct alc_spec *spec = codec->spec;
580
581 if (!spec->automute || !spec->detect_line)
582 return;
583 spec->line_jack_present =
584 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
585 spec->autocfg.line_out_pins);
586 update_speakers(codec);
587}
588
Takashi Iwai8d087c72011-06-28 12:45:47 +0200589#define get_connection_index(codec, mux, nid) \
590 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200591
Takashi Iwai1d045db2011-07-07 18:23:21 +0200592/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200593static void alc_mic_automute(struct hda_codec *codec)
594{
595 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200596 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200597
Takashi Iwai21268962011-07-07 15:01:13 +0200598 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200599 return;
600 if (snd_BUG_ON(!spec->adc_nids))
601 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200602 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200603 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200604
Takashi Iwai21268962011-07-07 15:01:13 +0200605 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
606 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
607 else if (spec->dock_mic_idx >= 0 &&
608 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
609 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
610 else
611 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200612
Takashi Iwai21268962011-07-07 15:01:13 +0200613 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
614 if (spec->dock_mic_idx >= 0)
615 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200616}
617
Kailang Yangc9b58002007-10-16 14:30:01 +0200618/* unsolicited event for HP jack sensing */
619static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
620{
621 if (codec->vendor_id == 0x10ec0880)
622 res >>= 28;
623 else
624 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200625 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200626 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200627 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200628 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200629 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200630 alc_line_automute(codec);
631 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200632 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200633 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200634 break;
635 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200636}
637
Takashi Iwai1d045db2011-07-07 18:23:21 +0200638/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200639static void alc_inithook(struct hda_codec *codec)
640{
Takashi Iwaid922b512011-04-28 12:18:53 +0200641 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200642 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200643 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200644}
645
Kailang Yangf9423e72008-05-27 12:32:25 +0200646/* additional initialization for ALC888 variants */
647static void alc888_coef_init(struct hda_codec *codec)
648{
649 unsigned int tmp;
650
651 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
652 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
653 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100654 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200655 /* alc888S-VC */
656 snd_hda_codec_read(codec, 0x20, 0,
657 AC_VERB_SET_PROC_COEF, 0x830);
658 else
659 /* alc888-VB */
660 snd_hda_codec_read(codec, 0x20, 0,
661 AC_VERB_SET_PROC_COEF, 0x3030);
662}
663
Takashi Iwai1d045db2011-07-07 18:23:21 +0200664/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200665static void alc889_coef_init(struct hda_codec *codec)
666{
667 unsigned int tmp;
668
669 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
670 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
671 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
672 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
673}
674
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100675/* turn on/off EAPD control (only if available) */
676static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
677{
678 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
679 return;
680 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
681 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
682 on ? 2 : 0);
683}
684
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200685/* turn on/off EAPD controls of the codec */
686static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
687{
688 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200689 static hda_nid_t pins[] = {
690 0x0f, 0x10, 0x14, 0x15, 0
691 };
692 hda_nid_t *p;
693 for (p = pins; *p; p++)
694 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200695}
696
Takashi Iwai1c716152011-04-07 10:37:16 +0200697/* generic shutup callback;
698 * just turning off EPAD and a little pause for avoiding pop-noise
699 */
700static void alc_eapd_shutup(struct hda_codec *codec)
701{
702 alc_auto_setup_eapd(codec, false);
703 msleep(200);
704}
705
Takashi Iwai1d045db2011-07-07 18:23:21 +0200706/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200707static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200708{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200709 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200710
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200711 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200712 switch (type) {
713 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200714 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
715 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200716 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200717 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
718 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200719 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200720 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
721 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200722 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200723 switch (codec->vendor_id) {
724 case 0x10ec0260:
725 snd_hda_codec_write(codec, 0x1a, 0,
726 AC_VERB_SET_COEF_INDEX, 7);
727 tmp = snd_hda_codec_read(codec, 0x1a, 0,
728 AC_VERB_GET_PROC_COEF, 0);
729 snd_hda_codec_write(codec, 0x1a, 0,
730 AC_VERB_SET_COEF_INDEX, 7);
731 snd_hda_codec_write(codec, 0x1a, 0,
732 AC_VERB_SET_PROC_COEF,
733 tmp | 0x2010);
734 break;
735 case 0x10ec0262:
736 case 0x10ec0880:
737 case 0x10ec0882:
738 case 0x10ec0883:
739 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100740 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100741 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200742 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200743 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200744 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200745 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200746 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100747#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200748 case 0x10ec0267:
749 case 0x10ec0268:
750 snd_hda_codec_write(codec, 0x20, 0,
751 AC_VERB_SET_COEF_INDEX, 7);
752 tmp = snd_hda_codec_read(codec, 0x20, 0,
753 AC_VERB_GET_PROC_COEF, 0);
754 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200755 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200756 snd_hda_codec_write(codec, 0x20, 0,
757 AC_VERB_SET_PROC_COEF,
758 tmp | 0x3000);
759 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100760#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200761 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200762 break;
763 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200764}
Kailang Yangea1fb292008-08-26 12:58:38 +0200765
Takashi Iwai1d045db2011-07-07 18:23:21 +0200766/*
767 * Auto-Mute mode mixer enum support
768 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200769static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
770 struct snd_ctl_elem_info *uinfo)
771{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200772 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
773 struct alc_spec *spec = codec->spec;
774 static const char * const texts2[] = {
775 "Disabled", "Enabled"
776 };
777 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200778 "Disabled", "Speaker Only", "Line-Out+Speaker"
779 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200780 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200781
782 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
783 uinfo->count = 1;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200784 if (spec->automute_hp_lo) {
785 uinfo->value.enumerated.items = 3;
786 texts = texts3;
787 } else {
788 uinfo->value.enumerated.items = 2;
789 texts = texts2;
790 }
791 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
792 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200793 strcpy(uinfo->value.enumerated.name,
794 texts[uinfo->value.enumerated.item]);
795 return 0;
796}
797
798static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
799 struct snd_ctl_elem_value *ucontrol)
800{
801 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
802 struct alc_spec *spec = codec->spec;
803 unsigned int val;
804 if (!spec->automute)
805 val = 0;
806 else if (!spec->automute_lines)
807 val = 1;
808 else
809 val = 2;
810 ucontrol->value.enumerated.item[0] = val;
811 return 0;
812}
813
814static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
815 struct snd_ctl_elem_value *ucontrol)
816{
817 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
818 struct alc_spec *spec = codec->spec;
819
820 switch (ucontrol->value.enumerated.item[0]) {
821 case 0:
822 if (!spec->automute)
823 return 0;
824 spec->automute = 0;
825 break;
826 case 1:
827 if (spec->automute && !spec->automute_lines)
828 return 0;
829 spec->automute = 1;
830 spec->automute_lines = 0;
831 break;
832 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200833 if (!spec->automute_hp_lo)
834 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200835 if (spec->automute && spec->automute_lines)
836 return 0;
837 spec->automute = 1;
838 spec->automute_lines = 1;
839 break;
840 default:
841 return -EINVAL;
842 }
843 update_speakers(codec);
844 return 1;
845}
846
Takashi Iwaia9111322011-05-02 11:30:18 +0200847static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200848 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
849 .name = "Auto-Mute Mode",
850 .info = alc_automute_mode_info,
851 .get = alc_automute_mode_get,
852 .put = alc_automute_mode_put,
853};
854
Takashi Iwai1d045db2011-07-07 18:23:21 +0200855static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
856{
857 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
858 return snd_array_new(&spec->kctls);
859}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200860
861static int alc_add_automute_mode_enum(struct hda_codec *codec)
862{
863 struct alc_spec *spec = codec->spec;
864 struct snd_kcontrol_new *knew;
865
866 knew = alc_kcontrol_new(spec);
867 if (!knew)
868 return -ENOMEM;
869 *knew = alc_automute_mode_enum;
870 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
871 if (!knew->name)
872 return -ENOMEM;
873 return 0;
874}
875
Takashi Iwai1d045db2011-07-07 18:23:21 +0200876/*
877 * Check the availability of HP/line-out auto-mute;
878 * Set up appropriately if really supported
879 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200880static void alc_init_auto_hp(struct hda_codec *codec)
881{
882 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200883 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200884 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200885 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200886
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200887 if (cfg->hp_pins[0])
888 present++;
889 if (cfg->line_out_pins[0])
890 present++;
891 if (cfg->speaker_pins[0])
892 present++;
893 if (present < 2) /* need two different output types */
894 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200895 if (present == 3)
896 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200897
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200898 if (!cfg->speaker_pins[0] &&
899 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200900 memcpy(cfg->speaker_pins, cfg->line_out_pins,
901 sizeof(cfg->speaker_pins));
902 cfg->speaker_outs = cfg->line_outs;
903 }
904
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200905 if (!cfg->hp_pins[0] &&
906 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200907 memcpy(cfg->hp_pins, cfg->line_out_pins,
908 sizeof(cfg->hp_pins));
909 cfg->hp_outs = cfg->line_outs;
910 }
911
912 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200913 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200914 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200915 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200916 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200917 nid);
918 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200919 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200920 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200921 spec->automute = 1;
922 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200923 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200924 if (spec->automute && cfg->line_out_pins[0] &&
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200925 cfg->speaker_pins[0] &&
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200926 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
927 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
928 for (i = 0; i < cfg->line_outs; i++) {
929 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200930 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200931 continue;
932 snd_printdd("realtek: Enable Line-Out auto-muting "
933 "on NID 0x%x\n", nid);
934 snd_hda_codec_write_cache(codec, nid, 0,
935 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200936 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200937 spec->detect_line = 1;
938 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200939 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200940 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200941
942 if (spec->automute) {
943 /* create a control for automute mode */
944 alc_add_automute_mode_enum(codec);
945 spec->unsol_event = alc_sku_unsol_event;
946 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200947}
948
Takashi Iwai1d045db2011-07-07 18:23:21 +0200949/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200950static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
951{
952 int i;
953 for (i = 0; i < nums; i++)
954 if (list[i] == nid)
955 return i;
956 return -1;
957}
958
Takashi Iwai1d045db2011-07-07 18:23:21 +0200959/* check whether dynamic ADC-switching is available */
960static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
961{
962 struct alc_spec *spec = codec->spec;
963 struct hda_input_mux *imux = &spec->private_imux[0];
964 int i, n, idx;
965 hda_nid_t cap, pin;
966
967 if (imux != spec->input_mux) /* no dynamic imux? */
968 return false;
969
970 for (n = 0; n < spec->num_adc_nids; n++) {
971 cap = spec->private_capsrc_nids[n];
972 for (i = 0; i < imux->num_items; i++) {
973 pin = spec->imux_pins[i];
974 if (!pin)
975 return false;
976 if (get_connection_index(codec, cap, pin) < 0)
977 break;
978 }
979 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +0200980 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +0200981 }
982
983 for (i = 0; i < imux->num_items; i++) {
984 pin = spec->imux_pins[i];
985 for (n = 0; n < spec->num_adc_nids; n++) {
986 cap = spec->private_capsrc_nids[n];
987 idx = get_connection_index(codec, cap, pin);
988 if (idx >= 0) {
989 imux->items[i].index = idx;
990 spec->dyn_adc_idx[i] = n;
991 break;
992 }
993 }
994 }
995
996 snd_printdd("realtek: enabling ADC switching\n");
997 spec->dyn_adc_switch = 1;
998 return true;
999}
Takashi Iwai21268962011-07-07 15:01:13 +02001000
1001/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1002static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1003{
1004 struct alc_spec *spec = codec->spec;
1005 struct hda_input_mux *imux;
1006 static char * const texts[3] = {
1007 "Mic", "Internal Mic", "Dock Mic"
1008 };
1009 int i;
1010
1011 if (!spec->auto_mic)
1012 return false;
1013 imux = &spec->private_imux[0];
1014 if (spec->input_mux == imux)
1015 return true;
1016 spec->imux_pins[0] = spec->ext_mic_pin;
1017 spec->imux_pins[1] = spec->int_mic_pin;
1018 spec->imux_pins[2] = spec->dock_mic_pin;
1019 for (i = 0; i < 3; i++) {
1020 strcpy(imux->items[i].label, texts[i]);
1021 if (spec->imux_pins[i])
1022 imux->num_items = i + 1;
1023 }
1024 spec->num_mux_defs = 1;
1025 spec->input_mux = imux;
1026 return true;
1027}
1028
1029/* check whether all auto-mic pins are valid; setup indices if OK */
1030static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1031{
1032 struct alc_spec *spec = codec->spec;
1033 const struct hda_input_mux *imux;
1034
1035 if (!spec->auto_mic)
1036 return false;
1037 if (spec->auto_mic_valid_imux)
1038 return true; /* already checked */
1039
1040 /* fill up imux indices */
1041 if (!alc_check_dyn_adc_switch(codec)) {
1042 spec->auto_mic = 0;
1043 return false;
1044 }
1045
1046 imux = spec->input_mux;
1047 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1048 spec->imux_pins, imux->num_items);
1049 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1050 spec->imux_pins, imux->num_items);
1051 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1052 spec->imux_pins, imux->num_items);
1053 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1054 spec->auto_mic = 0;
1055 return false; /* no corresponding imux */
1056 }
1057
1058 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1059 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001060 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001061 if (spec->dock_mic_pin)
1062 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1063 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001064 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001065
1066 spec->auto_mic_valid_imux = 1;
1067 spec->auto_mic = 1;
1068 return true;
1069}
1070
Takashi Iwai1d045db2011-07-07 18:23:21 +02001071/*
1072 * Check the availability of auto-mic switch;
1073 * Set up if really supported
1074 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001075static void alc_init_auto_mic(struct hda_codec *codec)
1076{
1077 struct alc_spec *spec = codec->spec;
1078 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001079 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001080 int i;
1081
Takashi Iwai21268962011-07-07 15:01:13 +02001082 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1083
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001084 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001085 for (i = 0; i < cfg->num_inputs; i++) {
1086 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001087 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001088 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001089 switch (snd_hda_get_input_pin_attr(defcfg)) {
1090 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001091 if (fixed)
1092 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001093 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1094 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001095 fixed = nid;
1096 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001097 case INPUT_PIN_ATTR_UNUSED:
1098 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001099 case INPUT_PIN_ATTR_DOCK:
1100 if (dock)
1101 return; /* already occupied */
1102 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1103 return; /* invalid type */
1104 dock = nid;
1105 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001106 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001107 if (ext)
1108 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001109 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1110 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001111 ext = nid;
1112 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001113 }
1114 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001115 if (!ext && dock) {
1116 ext = dock;
1117 dock = 0;
1118 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001119 if (!ext || !fixed)
1120 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001121 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001122 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001123 if (dock && !is_jack_detectable(codec, dock))
1124 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001125
1126 /* check imux indices */
1127 spec->ext_mic_pin = ext;
1128 spec->int_mic_pin = fixed;
1129 spec->dock_mic_pin = dock;
1130
1131 spec->auto_mic = 1;
1132 if (!alc_auto_mic_check_imux(codec))
1133 return;
1134
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001135 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1136 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001137 spec->unsol_event = alc_sku_unsol_event;
1138}
1139
Takashi Iwai1d045db2011-07-07 18:23:21 +02001140/* check the availabilities of auto-mute and auto-mic switches */
1141static void alc_auto_check_switches(struct hda_codec *codec)
1142{
1143 alc_init_auto_hp(codec);
1144 alc_init_auto_mic(codec);
1145}
1146
1147/*
1148 * Realtek SSID verification
1149 */
1150
David Henningsson90622912010-10-14 14:50:18 +02001151/* Could be any non-zero and even value. When used as fixup, tells
1152 * the driver to ignore any present sku defines.
1153 */
1154#define ALC_FIXUP_SKU_IGNORE (2)
1155
Kailang Yangda00c242010-03-19 11:23:45 +01001156static int alc_auto_parse_customize_define(struct hda_codec *codec)
1157{
1158 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001159 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001160 struct alc_spec *spec = codec->spec;
1161
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001162 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1163
David Henningsson90622912010-10-14 14:50:18 +02001164 if (spec->cdefine.fixup) {
1165 ass = spec->cdefine.sku_cfg;
1166 if (ass == ALC_FIXUP_SKU_IGNORE)
1167 return -1;
1168 goto do_sku;
1169 }
1170
Kailang Yangda00c242010-03-19 11:23:45 +01001171 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001172 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001173 goto do_sku;
1174
1175 nid = 0x1d;
1176 if (codec->vendor_id == 0x10ec0260)
1177 nid = 0x17;
1178 ass = snd_hda_codec_get_pincfg(codec, nid);
1179
1180 if (!(ass & 1)) {
1181 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1182 codec->chip_name, ass);
1183 return -1;
1184 }
1185
1186 /* check sum */
1187 tmp = 0;
1188 for (i = 1; i < 16; i++) {
1189 if ((ass >> i) & 1)
1190 tmp++;
1191 }
1192 if (((ass >> 16) & 0xf) != tmp)
1193 return -1;
1194
1195 spec->cdefine.port_connectivity = ass >> 30;
1196 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1197 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1198 spec->cdefine.customization = ass >> 8;
1199do_sku:
1200 spec->cdefine.sku_cfg = ass;
1201 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1202 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1203 spec->cdefine.swap = (ass & 0x2) >> 1;
1204 spec->cdefine.override = ass & 0x1;
1205
1206 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1207 nid, spec->cdefine.sku_cfg);
1208 snd_printd("SKU: port_connectivity=0x%x\n",
1209 spec->cdefine.port_connectivity);
1210 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1211 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1212 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1213 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1214 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1215 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1216 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1217
1218 return 0;
1219}
1220
Takashi Iwai1d045db2011-07-07 18:23:21 +02001221/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001222static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1223{
Takashi Iwai21268962011-07-07 15:01:13 +02001224 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001225}
1226
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001227/* check subsystem ID and set up device-specific initialization;
1228 * return 1 if initialized, 0 if invalid SSID
1229 */
1230/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1231 * 31 ~ 16 : Manufacture ID
1232 * 15 ~ 8 : SKU ID
1233 * 7 ~ 0 : Assembly ID
1234 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1235 */
1236static int alc_subsystem_id(struct hda_codec *codec,
1237 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001238 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001239{
1240 unsigned int ass, tmp, i;
1241 unsigned nid;
1242 struct alc_spec *spec = codec->spec;
1243
David Henningsson90622912010-10-14 14:50:18 +02001244 if (spec->cdefine.fixup) {
1245 ass = spec->cdefine.sku_cfg;
1246 if (ass == ALC_FIXUP_SKU_IGNORE)
1247 return 0;
1248 goto do_sku;
1249 }
1250
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001251 ass = codec->subsystem_id & 0xffff;
1252 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1253 goto do_sku;
1254
1255 /* invalid SSID, check the special NID pin defcfg instead */
1256 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001257 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001258 * 29~21 : reserve
1259 * 20 : PCBEEP input
1260 * 19~16 : Check sum (15:1)
1261 * 15~1 : Custom
1262 * 0 : override
1263 */
1264 nid = 0x1d;
1265 if (codec->vendor_id == 0x10ec0260)
1266 nid = 0x17;
1267 ass = snd_hda_codec_get_pincfg(codec, nid);
1268 snd_printd("realtek: No valid SSID, "
1269 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001270 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001271 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001272 return 0;
1273 if ((ass >> 30) != 1) /* no physical connection */
1274 return 0;
1275
1276 /* check sum */
1277 tmp = 0;
1278 for (i = 1; i < 16; i++) {
1279 if ((ass >> i) & 1)
1280 tmp++;
1281 }
1282 if (((ass >> 16) & 0xf) != tmp)
1283 return 0;
1284do_sku:
1285 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1286 ass & 0xffff, codec->vendor_id);
1287 /*
1288 * 0 : override
1289 * 1 : Swap Jack
1290 * 2 : 0 --> Desktop, 1 --> Laptop
1291 * 3~5 : External Amplifier control
1292 * 7~6 : Reserved
1293 */
1294 tmp = (ass & 0x38) >> 3; /* external Amp control */
1295 switch (tmp) {
1296 case 1:
1297 spec->init_amp = ALC_INIT_GPIO1;
1298 break;
1299 case 3:
1300 spec->init_amp = ALC_INIT_GPIO2;
1301 break;
1302 case 7:
1303 spec->init_amp = ALC_INIT_GPIO3;
1304 break;
1305 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001306 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001307 spec->init_amp = ALC_INIT_DEFAULT;
1308 break;
1309 }
1310
1311 /* is laptop or Desktop and enable the function "Mute internal speaker
1312 * when the external headphone out jack is plugged"
1313 */
1314 if (!(ass & 0x8000))
1315 return 1;
1316 /*
1317 * 10~8 : Jack location
1318 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1319 * 14~13: Resvered
1320 * 15 : 1 --> enable the function "Mute internal speaker
1321 * when the external headphone out jack is plugged"
1322 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001323 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001324 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001325 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1326 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001327 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001328 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001329 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001330 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001331 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001332 else if (tmp == 3)
1333 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001334 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001335 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001336 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1337 spec->autocfg.line_outs))
1338 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001339 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001340 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001341 return 1;
1342}
Kailang Yangea1fb292008-08-26 12:58:38 +02001343
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001344/* Check the validity of ALC subsystem-id
1345 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1346static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001347{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001348 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001349 struct alc_spec *spec = codec->spec;
1350 snd_printd("realtek: "
1351 "Enable default setup for auto mode as fallback\n");
1352 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001353 }
Takashi Iwai21268962011-07-07 15:01:13 +02001354}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001355
Takashi Iwai41e41f12005-06-08 14:48:49 +02001356/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001357 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001358 */
1359
1360struct alc_pincfg {
1361 hda_nid_t nid;
1362 u32 val;
1363};
1364
Todd Broche1eb5f12010-12-06 11:19:51 -08001365struct alc_model_fixup {
1366 const int id;
1367 const char *name;
1368};
1369
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001370struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001371 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001372 bool chained;
1373 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001374 union {
1375 unsigned int sku;
1376 const struct alc_pincfg *pins;
1377 const struct hda_verb *verbs;
1378 void (*func)(struct hda_codec *codec,
1379 const struct alc_fixup *fix,
1380 int action);
1381 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001382};
1383
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001384enum {
1385 ALC_FIXUP_INVALID,
1386 ALC_FIXUP_SKU,
1387 ALC_FIXUP_PINS,
1388 ALC_FIXUP_VERBS,
1389 ALC_FIXUP_FUNC,
1390};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001391
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001392enum {
1393 ALC_FIXUP_ACT_PRE_PROBE,
1394 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001395 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001396};
1397
1398static void alc_apply_fixup(struct hda_codec *codec, int action)
1399{
1400 struct alc_spec *spec = codec->spec;
1401 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001402#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001403 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001404#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001405 int depth = 0;
1406
1407 if (!spec->fixup_list)
1408 return;
1409
1410 while (id >= 0) {
1411 const struct alc_fixup *fix = spec->fixup_list + id;
1412 const struct alc_pincfg *cfg;
1413
1414 switch (fix->type) {
1415 case ALC_FIXUP_SKU:
1416 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1417 break;;
1418 snd_printdd(KERN_INFO "hda_codec: %s: "
1419 "Apply sku override for %s\n",
1420 codec->chip_name, modelname);
1421 spec->cdefine.sku_cfg = fix->v.sku;
1422 spec->cdefine.fixup = 1;
1423 break;
1424 case ALC_FIXUP_PINS:
1425 cfg = fix->v.pins;
1426 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1427 break;
1428 snd_printdd(KERN_INFO "hda_codec: %s: "
1429 "Apply pincfg for %s\n",
1430 codec->chip_name, modelname);
1431 for (; cfg->nid; cfg++)
1432 snd_hda_codec_set_pincfg(codec, cfg->nid,
1433 cfg->val);
1434 break;
1435 case ALC_FIXUP_VERBS:
1436 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1437 break;
1438 snd_printdd(KERN_INFO "hda_codec: %s: "
1439 "Apply fix-verbs for %s\n",
1440 codec->chip_name, modelname);
1441 add_verb(codec->spec, fix->v.verbs);
1442 break;
1443 case ALC_FIXUP_FUNC:
1444 if (!fix->v.func)
1445 break;
1446 snd_printdd(KERN_INFO "hda_codec: %s: "
1447 "Apply fix-func for %s\n",
1448 codec->chip_name, modelname);
1449 fix->v.func(codec, fix, action);
1450 break;
1451 default:
1452 snd_printk(KERN_ERR "hda_codec: %s: "
1453 "Invalid fixup type %d\n",
1454 codec->chip_name, fix->type);
1455 break;
1456 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001457 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001458 break;
1459 if (++depth > 10)
1460 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001461 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001462 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001463}
1464
Todd Broche1eb5f12010-12-06 11:19:51 -08001465static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001466 const struct alc_model_fixup *models,
1467 const struct snd_pci_quirk *quirk,
1468 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001469{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001470 struct alc_spec *spec = codec->spec;
1471 int id = -1;
1472 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001473
Todd Broche1eb5f12010-12-06 11:19:51 -08001474 if (codec->modelname && models) {
1475 while (models->name) {
1476 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001477 id = models->id;
1478 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001479 break;
1480 }
1481 models++;
1482 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001483 }
1484 if (id < 0) {
1485 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1486 if (quirk) {
1487 id = quirk->value;
1488#ifdef CONFIG_SND_DEBUG_VERBOSE
1489 name = quirk->name;
1490#endif
1491 }
1492 }
1493
1494 spec->fixup_id = id;
1495 if (id >= 0) {
1496 spec->fixup_list = fixlist;
1497 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001498 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001499}
1500
Takashi Iwai1d045db2011-07-07 18:23:21 +02001501/*
1502 * COEF access helper functions
1503 */
Kailang Yang274693f2009-12-03 10:07:50 +01001504static int alc_read_coef_idx(struct hda_codec *codec,
1505 unsigned int coef_idx)
1506{
1507 unsigned int val;
1508 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1509 coef_idx);
1510 val = snd_hda_codec_read(codec, 0x20, 0,
1511 AC_VERB_GET_PROC_COEF, 0);
1512 return val;
1513}
1514
Kailang Yang977ddd62010-09-15 10:02:29 +02001515static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1516 unsigned int coef_val)
1517{
1518 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1519 coef_idx);
1520 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1521 coef_val);
1522}
1523
Takashi Iwai1d045db2011-07-07 18:23:21 +02001524/*
1525 * Digital I/O handling
1526 */
1527
Takashi Iwai757899a2010-07-30 10:48:14 +02001528/* set right pin controls for digital I/O */
1529static void alc_auto_init_digital(struct hda_codec *codec)
1530{
1531 struct alc_spec *spec = codec->spec;
1532 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001533 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001534
1535 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1536 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001537 if (!pin)
1538 continue;
1539 snd_hda_codec_write(codec, pin, 0,
1540 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1541 if (!i)
1542 dac = spec->multiout.dig_out_nid;
1543 else
1544 dac = spec->slave_dig_outs[i - 1];
1545 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1546 continue;
1547 snd_hda_codec_write(codec, dac, 0,
1548 AC_VERB_SET_AMP_GAIN_MUTE,
1549 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001550 }
1551 pin = spec->autocfg.dig_in_pin;
1552 if (pin)
1553 snd_hda_codec_write(codec, pin, 0,
1554 AC_VERB_SET_PIN_WIDGET_CONTROL,
1555 PIN_IN);
1556}
1557
1558/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1559static void alc_auto_parse_digital(struct hda_codec *codec)
1560{
1561 struct alc_spec *spec = codec->spec;
1562 int i, err;
1563 hda_nid_t dig_nid;
1564
1565 /* support multiple SPDIFs; the secondary is set up as a slave */
1566 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001567 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001568 err = snd_hda_get_connections(codec,
1569 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001570 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001571 if (err < 0)
1572 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001573 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001574 if (!i) {
1575 spec->multiout.dig_out_nid = dig_nid;
1576 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1577 } else {
1578 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1579 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1580 break;
1581 spec->slave_dig_outs[i - 1] = dig_nid;
1582 }
1583 }
1584
1585 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001586 dig_nid = codec->start_nid;
1587 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1588 unsigned int wcaps = get_wcaps(codec, dig_nid);
1589 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1590 continue;
1591 if (!(wcaps & AC_WCAP_DIGITAL))
1592 continue;
1593 if (!(wcaps & AC_WCAP_CONN_LIST))
1594 continue;
1595 err = get_connection_index(codec, dig_nid,
1596 spec->autocfg.dig_in_pin);
1597 if (err >= 0) {
1598 spec->dig_in_nid = dig_nid;
1599 break;
1600 }
1601 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001602 }
1603}
1604
Takashi Iwaif95474e2007-07-10 00:47:43 +02001605/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001606 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001607 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001608static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1609 struct snd_ctl_elem_info *uinfo)
1610{
1611 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1612 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001613 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001614 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001615
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001616 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001617 if (spec->vol_in_capsrc)
1618 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1619 else
1620 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1621 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001622 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001623 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001624 return err;
1625}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001627static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1628 unsigned int size, unsigned int __user *tlv)
1629{
1630 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1631 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001632 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001633 int err;
1634
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001635 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001636 if (spec->vol_in_capsrc)
1637 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1638 else
1639 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1640 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001641 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001642 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001643 return err;
1644}
1645
1646typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1647 struct snd_ctl_elem_value *ucontrol);
1648
1649static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1650 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001651 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001652{
1653 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1654 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001655 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001656
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001657 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001658 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001659 for (i = 0; i < spec->num_adc_nids; i++) {
1660 kcontrol->private_value =
1661 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1662 3, 0, HDA_INPUT);
1663 err = func(kcontrol, ucontrol);
1664 if (err < 0)
1665 goto error;
1666 }
1667 } else {
1668 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001669 if (spec->vol_in_capsrc)
1670 kcontrol->private_value =
1671 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1672 3, 0, HDA_OUTPUT);
1673 else
1674 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001675 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1676 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001677 err = func(kcontrol, ucontrol);
1678 }
1679 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001680 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001681 return err;
1682}
1683
1684static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1685 struct snd_ctl_elem_value *ucontrol)
1686{
1687 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001688 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001689}
1690
1691static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1692 struct snd_ctl_elem_value *ucontrol)
1693{
1694 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001695 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001696}
1697
1698/* capture mixer elements */
1699#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1700
1701static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1702 struct snd_ctl_elem_value *ucontrol)
1703{
1704 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001705 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001706}
1707
1708static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1709 struct snd_ctl_elem_value *ucontrol)
1710{
1711 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001712 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001713}
1714
Takashi Iwaia23b6882009-03-23 15:21:36 +01001715#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001716 { \
1717 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1718 .name = "Capture Switch", \
1719 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1720 .count = num, \
1721 .info = alc_cap_sw_info, \
1722 .get = alc_cap_sw_get, \
1723 .put = alc_cap_sw_put, \
1724 }, \
1725 { \
1726 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1727 .name = "Capture Volume", \
1728 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1729 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1730 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1731 .count = num, \
1732 .info = alc_cap_vol_info, \
1733 .get = alc_cap_vol_get, \
1734 .put = alc_cap_vol_put, \
1735 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001736 }
1737
1738#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001739 { \
1740 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1741 /* .name = "Capture Source", */ \
1742 .name = "Input Source", \
1743 .count = num, \
1744 .info = alc_mux_enum_info, \
1745 .get = alc_mux_enum_get, \
1746 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001747 }
1748
1749#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001750static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001751 _DEFINE_CAPMIX(num), \
1752 _DEFINE_CAPSRC(num), \
1753 { } /* end */ \
1754}
1755
1756#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001757static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001758 _DEFINE_CAPMIX(num), \
1759 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001760}
1761
1762/* up to three ADCs */
1763DEFINE_CAPMIX(1);
1764DEFINE_CAPMIX(2);
1765DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001766DEFINE_CAPMIX_NOSRC(1);
1767DEFINE_CAPMIX_NOSRC(2);
1768DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001769
1770/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001771 * virtual master controls
1772 */
1773
1774/*
1775 * slave controls for virtual master
1776 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001777static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001778 "Front Playback Volume",
1779 "Surround Playback Volume",
1780 "Center Playback Volume",
1781 "LFE Playback Volume",
1782 "Side Playback Volume",
1783 "Headphone Playback Volume",
1784 "Speaker Playback Volume",
1785 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001786 "Line-Out Playback Volume",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001787 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001788 NULL,
1789};
1790
Takashi Iwaiea734962011-01-17 11:29:34 +01001791static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001792 "Front Playback Switch",
1793 "Surround Playback Switch",
1794 "Center Playback Switch",
1795 "LFE Playback Switch",
1796 "Side Playback Switch",
1797 "Headphone Playback Switch",
1798 "Speaker Playback Switch",
1799 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001800 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001801 "Line-Out Playback Switch",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001802 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001803 NULL,
1804};
1805
1806/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001807 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001809
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001810#define NID_MAPPING (-1)
1811
1812#define SUBDEV_SPEAKER_ (0 << 6)
1813#define SUBDEV_HP_ (1 << 6)
1814#define SUBDEV_LINE_ (2 << 6)
1815#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1816#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1817#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1818
Takashi Iwai603c4012008-07-30 15:01:44 +02001819static void alc_free_kctls(struct hda_codec *codec);
1820
Takashi Iwai67d634c2009-11-16 15:35:59 +01001821#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001822/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001823static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001824 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001825 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001826 { } /* end */
1827};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001828#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001829
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830static int alc_build_controls(struct hda_codec *codec)
1831{
1832 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001833 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001834 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001835 int i, j, err;
1836 unsigned int u;
1837 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838
1839 for (i = 0; i < spec->num_mixers; i++) {
1840 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1841 if (err < 0)
1842 return err;
1843 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001844 if (spec->cap_mixer) {
1845 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1846 if (err < 0)
1847 return err;
1848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001850 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001851 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001852 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 if (err < 0)
1854 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001855 if (!spec->no_analog) {
1856 err = snd_hda_create_spdif_share_sw(codec,
1857 &spec->multiout);
1858 if (err < 0)
1859 return err;
1860 spec->multiout.share_spdif = 1;
1861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 }
1863 if (spec->dig_in_nid) {
1864 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1865 if (err < 0)
1866 return err;
1867 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001868
Takashi Iwai67d634c2009-11-16 15:35:59 +01001869#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001870 /* create beep controls if needed */
1871 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001872 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001873 for (knew = alc_beep_mixer; knew->name; knew++) {
1874 struct snd_kcontrol *kctl;
1875 kctl = snd_ctl_new1(knew, codec);
1876 if (!kctl)
1877 return -ENOMEM;
1878 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001879 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001880 if (err < 0)
1881 return err;
1882 }
1883 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001884#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001885
Takashi Iwai2134ea42008-01-10 16:53:55 +01001886 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001887 if (!spec->no_analog &&
1888 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001889 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001890 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001891 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001892 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001893 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001894 if (err < 0)
1895 return err;
1896 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001897 if (!spec->no_analog &&
1898 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001899 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1900 NULL, alc_slave_sws);
1901 if (err < 0)
1902 return err;
1903 }
1904
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001905 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001906 if (spec->capsrc_nids || spec->adc_nids) {
1907 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1908 if (!kctl)
1909 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1910 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001911 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001912 if (!nids)
1913 nids = spec->adc_nids;
1914 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1915 if (err < 0)
1916 return err;
1917 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001918 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001919 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001920 const char *kname = kctl ? kctl->id.name : NULL;
1921 for (knew = spec->cap_mixer; knew->name; knew++) {
1922 if (kname && strcmp(knew->name, kname) == 0)
1923 continue;
1924 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1925 for (i = 0; kctl && i < kctl->count; i++) {
1926 err = snd_hda_add_nid(codec, kctl, i,
1927 spec->adc_nids[i]);
1928 if (err < 0)
1929 return err;
1930 }
1931 }
1932 }
1933
1934 /* other nid->control mapping */
1935 for (i = 0; i < spec->num_mixers; i++) {
1936 for (knew = spec->mixers[i]; knew->name; knew++) {
1937 if (knew->iface != NID_MAPPING)
1938 continue;
1939 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1940 if (kctl == NULL)
1941 continue;
1942 u = knew->subdevice;
1943 for (j = 0; j < 4; j++, u >>= 8) {
1944 nid = u & 0x3f;
1945 if (nid == 0)
1946 continue;
1947 switch (u & 0xc0) {
1948 case SUBDEV_SPEAKER_:
1949 nid = spec->autocfg.speaker_pins[nid];
1950 break;
1951 case SUBDEV_LINE_:
1952 nid = spec->autocfg.line_out_pins[nid];
1953 break;
1954 case SUBDEV_HP_:
1955 nid = spec->autocfg.hp_pins[nid];
1956 break;
1957 default:
1958 continue;
1959 }
1960 err = snd_hda_add_nid(codec, kctl, 0, nid);
1961 if (err < 0)
1962 return err;
1963 }
1964 u = knew->private_value;
1965 for (j = 0; j < 4; j++, u >>= 8) {
1966 nid = u & 0xff;
1967 if (nid == 0)
1968 continue;
1969 err = snd_hda_add_nid(codec, kctl, 0, nid);
1970 if (err < 0)
1971 return err;
1972 }
1973 }
1974 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001975
1976 alc_free_kctls(codec); /* no longer needed */
1977
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 return 0;
1979}
1980
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001981
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001983 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001984 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001985
Takashi Iwai584c0c42011-03-10 12:51:11 +01001986static void alc_init_special_input_src(struct hda_codec *codec);
1987
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988static int alc_init(struct hda_codec *codec)
1989{
1990 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001991 unsigned int i;
1992
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001993 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001994 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001995
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001996 for (i = 0; i < spec->num_init_verbs; i++)
1997 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01001998 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001999
2000 if (spec->init_hook)
2001 spec->init_hook(codec);
2002
Takashi Iwai58701122011-01-13 15:41:45 +01002003 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2004
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002005 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 return 0;
2007}
2008
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002009static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2010{
2011 struct alc_spec *spec = codec->spec;
2012
2013 if (spec->unsol_event)
2014 spec->unsol_event(codec, res);
2015}
2016
Takashi Iwaicb53c622007-08-10 17:21:45 +02002017#ifdef CONFIG_SND_HDA_POWER_SAVE
2018static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2019{
2020 struct alc_spec *spec = codec->spec;
2021 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2022}
2023#endif
2024
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025/*
2026 * Analog playback callbacks
2027 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002028static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002030 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031{
2032 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002033 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2034 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035}
2036
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002037static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 struct hda_codec *codec,
2039 unsigned int stream_tag,
2040 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002041 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042{
2043 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002044 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2045 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046}
2047
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002048static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002050 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051{
2052 struct alc_spec *spec = codec->spec;
2053 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2054}
2055
2056/*
2057 * Digital out
2058 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002059static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002061 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062{
2063 struct alc_spec *spec = codec->spec;
2064 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2065}
2066
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002067static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002068 struct hda_codec *codec,
2069 unsigned int stream_tag,
2070 unsigned int format,
2071 struct snd_pcm_substream *substream)
2072{
2073 struct alc_spec *spec = codec->spec;
2074 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2075 stream_tag, format, substream);
2076}
2077
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002078static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002079 struct hda_codec *codec,
2080 struct snd_pcm_substream *substream)
2081{
2082 struct alc_spec *spec = codec->spec;
2083 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2084}
2085
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002086static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002088 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089{
2090 struct alc_spec *spec = codec->spec;
2091 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2092}
2093
2094/*
2095 * Analog capture
2096 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002097static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 struct hda_codec *codec,
2099 unsigned int stream_tag,
2100 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002101 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102{
2103 struct alc_spec *spec = codec->spec;
2104
Takashi Iwai63300792008-01-24 15:31:36 +01002105 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 stream_tag, 0, format);
2107 return 0;
2108}
2109
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002110static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002112 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113{
2114 struct alc_spec *spec = codec->spec;
2115
Takashi Iwai888afa12008-03-18 09:57:50 +01002116 snd_hda_codec_cleanup_stream(codec,
2117 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 return 0;
2119}
2120
Takashi Iwai840b64c2010-07-13 22:49:01 +02002121/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002122static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002123 struct hda_codec *codec,
2124 unsigned int stream_tag,
2125 unsigned int format,
2126 struct snd_pcm_substream *substream)
2127{
2128 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002129 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002130 spec->cur_adc_stream_tag = stream_tag;
2131 spec->cur_adc_format = format;
2132 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2133 return 0;
2134}
2135
Takashi Iwai21268962011-07-07 15:01:13 +02002136static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002137 struct hda_codec *codec,
2138 struct snd_pcm_substream *substream)
2139{
2140 struct alc_spec *spec = codec->spec;
2141 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2142 spec->cur_adc = 0;
2143 return 0;
2144}
2145
Takashi Iwai21268962011-07-07 15:01:13 +02002146static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002147 .substreams = 1,
2148 .channels_min = 2,
2149 .channels_max = 2,
2150 .nid = 0, /* fill later */
2151 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002152 .prepare = dyn_adc_capture_pcm_prepare,
2153 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002154 },
2155};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156
2157/*
2158 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002159static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 .substreams = 1,
2161 .channels_min = 2,
2162 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002163 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002165 .open = alc_playback_pcm_open,
2166 .prepare = alc_playback_pcm_prepare,
2167 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 },
2169};
2170
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002171static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002172 .substreams = 1,
2173 .channels_min = 2,
2174 .channels_max = 2,
2175 /* NID is set in alc_build_pcms */
2176};
2177
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002178static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002179 .substreams = 1,
2180 .channels_min = 2,
2181 .channels_max = 2,
2182 /* NID is set in alc_build_pcms */
2183};
2184
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002185static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002186 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 .channels_min = 2,
2188 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002189 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002191 .prepare = alc_alt_capture_pcm_prepare,
2192 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 },
2194};
2195
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002196static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 .substreams = 1,
2198 .channels_min = 2,
2199 .channels_max = 2,
2200 /* NID is set in alc_build_pcms */
2201 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002202 .open = alc_dig_playback_pcm_open,
2203 .close = alc_dig_playback_pcm_close,
2204 .prepare = alc_dig_playback_pcm_prepare,
2205 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 },
2207};
2208
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002209static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 .substreams = 1,
2211 .channels_min = 2,
2212 .channels_max = 2,
2213 /* NID is set in alc_build_pcms */
2214};
2215
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002216/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002217static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002218 .substreams = 0,
2219 .channels_min = 0,
2220 .channels_max = 0,
2221};
2222
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223static int alc_build_pcms(struct hda_codec *codec)
2224{
2225 struct alc_spec *spec = codec->spec;
2226 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002227 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 int i;
2229
2230 codec->num_pcms = 1;
2231 codec->pcm_info = info;
2232
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002233 if (spec->no_analog)
2234 goto skip_analog;
2235
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002236 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2237 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002239
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002240 if (spec->multiout.dac_nids > 0) {
2241 p = spec->stream_analog_playback;
2242 if (!p)
2243 p = &alc_pcm_analog_playback;
2244 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002245 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2246 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002247 if (spec->adc_nids) {
2248 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002249 if (!p) {
2250 if (spec->dyn_adc_switch)
2251 p = &dyn_adc_pcm_analog_capture;
2252 else
2253 p = &alc_pcm_analog_capture;
2254 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002255 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002256 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
Takashi Iwai4a471b72005-12-07 13:56:29 +01002259 if (spec->channel_mode) {
2260 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2261 for (i = 0; i < spec->num_channel_mode; i++) {
2262 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2263 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 }
2266 }
2267
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002268 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002269 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002271 snprintf(spec->stream_name_digital,
2272 sizeof(spec->stream_name_digital),
2273 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002274 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002275 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002276 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002278 if (spec->dig_out_type)
2279 info->pcm_type = spec->dig_out_type;
2280 else
2281 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002282 if (spec->multiout.dig_out_nid) {
2283 p = spec->stream_digital_playback;
2284 if (!p)
2285 p = &alc_pcm_digital_playback;
2286 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2288 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002289 if (spec->dig_in_nid) {
2290 p = spec->stream_digital_capture;
2291 if (!p)
2292 p = &alc_pcm_digital_capture;
2293 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2295 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002296 /* FIXME: do we need this for all Realtek codec models? */
2297 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 }
2299
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002300 if (spec->no_analog)
2301 return 0;
2302
Takashi Iwaie08a0072006-09-07 17:52:14 +02002303 /* If the use of more than one ADC is requested for the current
2304 * model, configure a second analog capture-only PCM.
2305 */
2306 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002307 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002308 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002309 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002310 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002311 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002312 p = spec->stream_analog_alt_playback;
2313 if (!p)
2314 p = &alc_pcm_analog_alt_playback;
2315 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002316 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2317 spec->alt_dac_nid;
2318 } else {
2319 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2320 alc_pcm_null_stream;
2321 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2322 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002323 if (spec->num_adc_nids > 1) {
2324 p = spec->stream_analog_alt_capture;
2325 if (!p)
2326 p = &alc_pcm_analog_alt_capture;
2327 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002328 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2329 spec->adc_nids[1];
2330 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2331 spec->num_adc_nids - 1;
2332 } else {
2333 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2334 alc_pcm_null_stream;
2335 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002336 }
2337 }
2338
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 return 0;
2340}
2341
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002342static inline void alc_shutup(struct hda_codec *codec)
2343{
Takashi Iwai1c716152011-04-07 10:37:16 +02002344 struct alc_spec *spec = codec->spec;
2345
2346 if (spec && spec->shutup)
2347 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002348 snd_hda_shutup_pins(codec);
2349}
2350
Takashi Iwai603c4012008-07-30 15:01:44 +02002351static void alc_free_kctls(struct hda_codec *codec)
2352{
2353 struct alc_spec *spec = codec->spec;
2354
2355 if (spec->kctls.list) {
2356 struct snd_kcontrol_new *kctl = spec->kctls.list;
2357 int i;
2358 for (i = 0; i < spec->kctls.used; i++)
2359 kfree(kctl[i].name);
2360 }
2361 snd_array_free(&spec->kctls);
2362}
2363
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364static void alc_free(struct hda_codec *codec)
2365{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002366 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002367
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002368 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002369 return;
2370
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002371 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002372 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002373 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002374 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002375 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376}
2377
Hector Martinf5de24b2009-12-20 22:51:31 +01002378#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002379static void alc_power_eapd(struct hda_codec *codec)
2380{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002381 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002382}
2383
Hector Martinf5de24b2009-12-20 22:51:31 +01002384static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2385{
2386 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002387 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002388 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002389 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002390 return 0;
2391}
2392#endif
2393
Takashi Iwai2a439522011-07-26 09:52:50 +02002394#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002395static int alc_resume(struct hda_codec *codec)
2396{
Takashi Iwai1c716152011-04-07 10:37:16 +02002397 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002398 codec->patch_ops.init(codec);
2399 snd_hda_codec_resume_amp(codec);
2400 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002401 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002402 return 0;
2403}
Takashi Iwaie044c392008-10-27 16:56:24 +01002404#endif
2405
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406/*
2407 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002408static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 .build_controls = alc_build_controls,
2410 .build_pcms = alc_build_pcms,
2411 .init = alc_init,
2412 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002413 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002414#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002415 .resume = alc_resume,
2416#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002417#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002418 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002419 .check_power_status = alc_check_power_status,
2420#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002421 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422};
2423
Kailang Yangc027ddc2010-03-19 11:33:06 +01002424/* replace the codec chip_name with the given string */
2425static int alc_codec_rename(struct hda_codec *codec, const char *name)
2426{
2427 kfree(codec->chip_name);
2428 codec->chip_name = kstrdup(name, GFP_KERNEL);
2429 if (!codec->chip_name) {
2430 alc_free(codec);
2431 return -ENOMEM;
2432 }
2433 return 0;
2434}
2435
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002436/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002437 * Automatic parse of I/O pins from the BIOS configuration
2438 */
2439
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002440enum {
2441 ALC_CTL_WIDGET_VOL,
2442 ALC_CTL_WIDGET_MUTE,
2443 ALC_CTL_BIND_MUTE,
2444};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002445static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002446 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2447 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002448 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002449};
2450
2451/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002452static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002453 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002454{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002455 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002456
Takashi Iwaice764ab2011-04-27 16:35:23 +02002457 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002458 if (!knew)
2459 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002460 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002461 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002462 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002463 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002464 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002465 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002466 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002467 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002468 return 0;
2469}
2470
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002471static int add_control_with_pfx(struct alc_spec *spec, int type,
2472 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002473 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002474{
2475 char name[32];
2476 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002477 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002478}
2479
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002480#define add_pb_vol_ctrl(spec, type, pfx, val) \
2481 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2482#define add_pb_sw_ctrl(spec, type, pfx, val) \
2483 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2484#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2485 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2486#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2487 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002488
Takashi Iwai6843ca12011-06-24 11:03:58 +02002489static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2490 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002491{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002492 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002493 static const char * const chname[4] = {
2494 "Front", "Surround", NULL /*CLFE*/, "Side"
2495 };
Takashi Iwaice764ab2011-04-27 16:35:23 +02002496
Takashi Iwai6843ca12011-06-24 11:03:58 +02002497 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002498 if (cfg->line_outs == 1 && !spec->multi_ios &&
2499 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002500 return "Master";
2501
2502 switch (cfg->line_out_type) {
2503 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002504 if (cfg->line_outs == 1)
2505 return "Speaker";
2506 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002507 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002508 /* for multi-io case, only the primary out */
2509 if (ch && spec->multi_ios)
2510 break;
2511 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002512 return "Headphone";
2513 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002514 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002515 return "PCM";
2516 break;
2517 }
Takashi Iwai6843ca12011-06-24 11:03:58 +02002518 return chname[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002519}
2520
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002521/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002522static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002523 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002524 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002525{
Kailang Yangdf694da2005-12-05 19:42:22 +01002526 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002527
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002528 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002529 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2530 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002531 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002532 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002533 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2534 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002535 return err;
2536 return 0;
2537}
2538
Takashi Iwai05f5f472009-08-25 13:10:18 +02002539static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002540{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002541 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2542 return (pincap & AC_PINCAP_IN) != 0;
2543}
2544
Takashi Iwai1d045db2011-07-07 18:23:21 +02002545/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002546static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002547{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002548 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002549 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002550 hda_nid_t *adc_nids = spec->private_adc_nids;
2551 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2552 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2553 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002554 int i, nums = 0;
2555
2556 nid = codec->start_nid;
2557 for (i = 0; i < codec->num_nodes; i++, nid++) {
2558 hda_nid_t src;
2559 const hda_nid_t *list;
2560 unsigned int caps = get_wcaps(codec, nid);
2561 int type = get_wcaps_type(caps);
2562
2563 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2564 continue;
2565 adc_nids[nums] = nid;
2566 cap_nids[nums] = nid;
2567 src = nid;
2568 for (;;) {
2569 int n;
2570 type = get_wcaps_type(get_wcaps(codec, src));
2571 if (type == AC_WID_PIN)
2572 break;
2573 if (type == AC_WID_AUD_SEL) {
2574 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002575 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002576 break;
2577 }
2578 n = snd_hda_get_conn_list(codec, src, &list);
2579 if (n > 1) {
2580 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002581 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002582 break;
2583 } else if (n != 1)
2584 break;
2585 src = *list;
2586 }
2587 if (++nums >= max_nums)
2588 break;
2589 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002590 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002591 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002592 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002593 return nums;
2594}
2595
Takashi Iwai05f5f472009-08-25 13:10:18 +02002596/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002597static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002598{
2599 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002600 const struct auto_pin_cfg *cfg = &spec->autocfg;
2601 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002602 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002603 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002604 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002605 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002606
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002607 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002608 if (num_adcs < 0)
2609 return 0;
2610
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002611 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002612 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002613 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002614
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002615 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002616 if (!alc_is_input_pin(codec, pin))
2617 continue;
2618
David Henningsson5322bf22011-01-05 11:03:56 +01002619 label = hda_get_autocfg_input_label(codec, cfg, i);
2620 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002621 type_idx++;
2622 else
2623 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002624 prev_label = label;
2625
Takashi Iwai05f5f472009-08-25 13:10:18 +02002626 if (mixer) {
2627 idx = get_connection_index(codec, mixer, pin);
2628 if (idx >= 0) {
2629 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002630 label, type_idx,
2631 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002632 if (err < 0)
2633 return err;
2634 }
2635 }
2636
Takashi Iwaib7821702011-07-06 15:12:46 +02002637 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002638 hda_nid_t cap = spec->capsrc_nids ?
2639 spec->capsrc_nids[c] : spec->adc_nids[c];
2640 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002641 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002642 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002643 snd_hda_add_imux_item(imux, label, idx, NULL);
2644 break;
2645 }
2646 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002647 }
Takashi Iwai21268962011-07-07 15:01:13 +02002648
2649 spec->num_mux_defs = 1;
2650 spec->input_mux = imux;
2651
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002652 return 0;
2653}
2654
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002655static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2656 unsigned int pin_type)
2657{
2658 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2659 pin_type);
2660 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002661 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2662 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002663 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002664}
2665
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002666static int get_pin_type(int line_out_type)
2667{
2668 if (line_out_type == AUTO_PIN_HP_OUT)
2669 return PIN_HP;
2670 else
2671 return PIN_OUT;
2672}
2673
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002674static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002675{
2676 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002677 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002678 int i;
2679
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002680 for (i = 0; i < cfg->num_inputs; i++) {
2681 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002682 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002683 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002684 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002685 snd_hda_codec_write(codec, nid, 0,
2686 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002687 AMP_OUT_MUTE);
2688 }
2689 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002690
2691 /* mute all loopback inputs */
2692 if (spec->mixer_nid) {
2693 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2694 for (i = 0; i < nums; i++)
2695 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2696 AC_VERB_SET_AMP_GAIN_MUTE,
2697 AMP_IN_MUTE(i));
2698 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002699}
2700
Takashi Iwai7085ec12009-10-02 09:03:58 +02002701/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002702static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002703{
Takashi Iwai604401a2011-04-27 15:14:23 +02002704 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002705 int i, num;
2706
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002707 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2708 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002709 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2710 for (i = 0; i < num; i++) {
2711 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2712 return list[i];
2713 }
2714 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002715}
2716
Takashi Iwai604401a2011-04-27 15:14:23 +02002717/* go down to the selector widget before the mixer */
2718static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2719{
2720 hda_nid_t srcs[5];
2721 int num = snd_hda_get_connections(codec, pin, srcs,
2722 ARRAY_SIZE(srcs));
2723 if (num != 1 ||
2724 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2725 return pin;
2726 return srcs[0];
2727}
2728
Takashi Iwai7085ec12009-10-02 09:03:58 +02002729/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002730static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002731 hda_nid_t dac)
2732{
David Henningssoncc1c4522010-11-24 14:17:47 +01002733 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002734 int i, num;
2735
Takashi Iwai604401a2011-04-27 15:14:23 +02002736 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002737 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2738 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002739 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002740 return mix[i];
2741 }
2742 return 0;
2743}
2744
Takashi Iwaice764ab2011-04-27 16:35:23 +02002745/* select the connection from pin to DAC if needed */
2746static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2747 hda_nid_t dac)
2748{
2749 hda_nid_t mix[5];
2750 int i, num;
2751
2752 pin = alc_go_down_to_selector(codec, pin);
2753 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2754 if (num < 2)
2755 return 0;
2756 for (i = 0; i < num; i++) {
2757 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2758 snd_hda_codec_update_cache(codec, pin, 0,
2759 AC_VERB_SET_CONNECT_SEL, i);
2760 return 0;
2761 }
2762 }
2763 return 0;
2764}
2765
Takashi Iwai7085ec12009-10-02 09:03:58 +02002766/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002767static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002768{
2769 struct alc_spec *spec = codec->spec;
2770 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002771 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002772
Takashi Iwai604401a2011-04-27 15:14:23 +02002773 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002774 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002775 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002776 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002777 if (!nid)
2778 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002779 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2780 spec->multiout.num_dacs))
2781 continue;
2782 if (spec->multiout.hp_nid == nid)
2783 continue;
2784 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2785 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2786 continue;
2787 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002788 }
2789 return 0;
2790}
2791
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002792static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2793{
2794 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2795 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2796 return alc_auto_look_for_dac(codec, pin);
2797 return 0;
2798}
2799
Takashi Iwai7085ec12009-10-02 09:03:58 +02002800/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002801static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002802{
2803 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002804 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002805 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002806 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002807
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002808 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002809 /* set num_dacs once to full for alc_auto_look_for_dac() */
2810 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002811 spec->multiout.hp_nid = 0;
2812 spec->multiout.extra_out_nid[0] = 0;
2813 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2814 spec->multiout.dac_nids = spec->private_dac_nids;
2815
2816 /* fill hard-wired DACs first */
2817 if (!redone) {
2818 for (i = 0; i < cfg->line_outs; i++)
2819 spec->private_dac_nids[i] =
2820 get_dac_if_single(codec, cfg->line_out_pins[i]);
2821 if (cfg->hp_outs)
2822 spec->multiout.hp_nid =
2823 get_dac_if_single(codec, cfg->hp_pins[0]);
2824 if (cfg->speaker_outs)
2825 spec->multiout.extra_out_nid[0] =
2826 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002827 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002828
2829 for (i = 0; i < cfg->line_outs; i++) {
2830 hda_nid_t pin = cfg->line_out_pins[i];
2831 if (spec->private_dac_nids[i])
2832 continue;
2833 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2834 if (!spec->private_dac_nids[i] && !redone) {
2835 /* if we can't find primary DACs, re-probe without
2836 * checking the hard-wired DACs
2837 */
2838 redone = true;
2839 goto again;
2840 }
2841 }
2842
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002843 /* re-count num_dacs and squash invalid entries */
2844 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002845 for (i = 0; i < cfg->line_outs; i++) {
2846 if (spec->private_dac_nids[i])
2847 spec->multiout.num_dacs++;
2848 else
2849 memmove(spec->private_dac_nids + i,
2850 spec->private_dac_nids + i + 1,
2851 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2852 }
2853
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002854 if (cfg->hp_outs && !spec->multiout.hp_nid)
2855 spec->multiout.hp_nid =
2856 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2857 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2858 spec->multiout.extra_out_nid[0] =
2859 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2860
Takashi Iwai7085ec12009-10-02 09:03:58 +02002861 return 0;
2862}
2863
Takashi Iwai343a04b2011-07-06 14:28:39 +02002864static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002865 const char *pfx, int cidx,
2866 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002867{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002868 if (!nid)
2869 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002870 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2871 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002872}
2873
Takashi Iwai343a04b2011-07-06 14:28:39 +02002874#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2875 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002876
2877/* create a mute-switch for the given mixer widget;
2878 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2879 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002880static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002881 const char *pfx, int cidx,
2882 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002883{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002884 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002885 int type;
2886 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002887 if (!nid)
2888 return 0;
2889 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2890 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2891 type = ALC_CTL_WIDGET_MUTE;
2892 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2893 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002894 type = ALC_CTL_WIDGET_MUTE;
2895 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2896 } else {
2897 type = ALC_CTL_BIND_MUTE;
2898 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2899 }
2900 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002901}
2902
Takashi Iwai343a04b2011-07-06 14:28:39 +02002903#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2904 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002905
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002906static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2907 hda_nid_t pin, hda_nid_t dac)
2908{
2909 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2910 if (nid_has_mute(codec, pin, HDA_OUTPUT))
2911 return pin;
2912 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
2913 return mix;
2914 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
2915 return dac;
2916 return 0;
2917}
2918
2919static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
2920 hda_nid_t pin, hda_nid_t dac)
2921{
2922 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2923 if (nid_has_volume(codec, dac, HDA_OUTPUT))
2924 return dac;
2925 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
2926 return mix;
2927 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
2928 return pin;
2929 return 0;
2930}
2931
Takashi Iwai7085ec12009-10-02 09:03:58 +02002932/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002933static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002934 const struct auto_pin_cfg *cfg)
2935{
2936 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002937 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002938
Takashi Iwaice764ab2011-04-27 16:35:23 +02002939 noutputs = cfg->line_outs;
2940 if (spec->multi_ios > 0)
2941 noutputs += spec->multi_ios;
2942
2943 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002944 const char *name;
2945 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002946 hda_nid_t dac, pin;
2947 hda_nid_t sw, vol;
2948
2949 dac = spec->multiout.dac_nids[i];
2950 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002951 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002952 if (i >= cfg->line_outs)
2953 pin = spec->multi_io[i - 1].pin;
2954 else
2955 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002956
2957 sw = alc_look_for_out_mute_nid(codec, pin, dac);
2958 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02002959 name = alc_get_line_out_pfx(spec, i, true, &index);
2960 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002961 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002962 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002963 if (err < 0)
2964 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002965 err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002966 if (err < 0)
2967 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002968 err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002969 if (err < 0)
2970 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002971 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002972 if (err < 0)
2973 return err;
2974 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002975 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002976 if (err < 0)
2977 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002978 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002979 if (err < 0)
2980 return err;
2981 }
2982 }
2983 return 0;
2984}
2985
2986/* add playback controls for speaker and HP outputs */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002987static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002988 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002989{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002990 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002991 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002992 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002993
2994 if (!pin)
2995 return 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002996 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02002997 /* the corresponding DAC is already occupied */
2998 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
2999 return 0; /* no way */
3000 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02003001 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003002 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3003 }
3004
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003005 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3006 vol = alc_look_for_out_vol_nid(codec, pin, dac);
3007 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003008 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003009 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003010 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003011 if (err < 0)
3012 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003013 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003014}
3015
Takashi Iwai343a04b2011-07-06 14:28:39 +02003016static int alc_auto_create_hp_out(struct hda_codec *codec)
3017{
3018 struct alc_spec *spec = codec->spec;
3019 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3020 spec->multiout.hp_nid,
3021 "Headphone");
3022}
3023
3024static int alc_auto_create_speaker_out(struct hda_codec *codec)
3025{
3026 struct alc_spec *spec = codec->spec;
3027 return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
3028 spec->multiout.extra_out_nid[0],
3029 "Speaker");
3030}
3031
Takashi Iwai343a04b2011-07-06 14:28:39 +02003032static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003033 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003034 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003035{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003036 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003037 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003038 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003039
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003040 alc_set_pin_output(codec, pin, pin_type);
3041 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003042 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003043 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003044 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003045 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003046 mix = srcs[i];
3047 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003048 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003049 if (!mix)
3050 return;
3051
3052 /* need the manual connection? */
3053 if (num > 1)
3054 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3055 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003056 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3057 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003058 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003059 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003060 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003061 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003062 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003063 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3064 if (nid)
3065 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3066 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003067}
3068
Takashi Iwai343a04b2011-07-06 14:28:39 +02003069static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003070{
3071 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003072 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003073 int i;
3074
3075 for (i = 0; i <= HDA_SIDE; i++) {
3076 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3077 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003078 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003079 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003080 }
3081}
3082
Takashi Iwai343a04b2011-07-06 14:28:39 +02003083static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003084{
3085 struct alc_spec *spec = codec->spec;
3086 hda_nid_t pin;
3087
3088 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003089 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003090 alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003091 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003092 pin = spec->autocfg.speaker_pins[0];
3093 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003094 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003095 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003096}
3097
Takashi Iwaice764ab2011-04-27 16:35:23 +02003098/*
3099 * multi-io helper
3100 */
3101static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3102 unsigned int location)
3103{
3104 struct alc_spec *spec = codec->spec;
3105 struct auto_pin_cfg *cfg = &spec->autocfg;
3106 int type, i, num_pins = 0;
3107
3108 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3109 for (i = 0; i < cfg->num_inputs; i++) {
3110 hda_nid_t nid = cfg->inputs[i].pin;
3111 hda_nid_t dac;
3112 unsigned int defcfg, caps;
3113 if (cfg->inputs[i].type != type)
3114 continue;
3115 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3116 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3117 continue;
3118 if (location && get_defcfg_location(defcfg) != location)
3119 continue;
3120 caps = snd_hda_query_pin_caps(codec, nid);
3121 if (!(caps & AC_PINCAP_OUT))
3122 continue;
3123 dac = alc_auto_look_for_dac(codec, nid);
3124 if (!dac)
3125 continue;
3126 spec->multi_io[num_pins].pin = nid;
3127 spec->multi_io[num_pins].dac = dac;
3128 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003129 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003130 }
3131 }
3132 spec->multiout.num_dacs = 1;
3133 if (num_pins < 2)
3134 return 0;
3135 return num_pins;
3136}
3137
3138static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3139 struct snd_ctl_elem_info *uinfo)
3140{
3141 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3142 struct alc_spec *spec = codec->spec;
3143
3144 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3145 uinfo->count = 1;
3146 uinfo->value.enumerated.items = spec->multi_ios + 1;
3147 if (uinfo->value.enumerated.item > spec->multi_ios)
3148 uinfo->value.enumerated.item = spec->multi_ios;
3149 sprintf(uinfo->value.enumerated.name, "%dch",
3150 (uinfo->value.enumerated.item + 1) * 2);
3151 return 0;
3152}
3153
3154static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3155 struct snd_ctl_elem_value *ucontrol)
3156{
3157 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3158 struct alc_spec *spec = codec->spec;
3159 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3160 return 0;
3161}
3162
3163static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3164{
3165 struct alc_spec *spec = codec->spec;
3166 hda_nid_t nid = spec->multi_io[idx].pin;
3167
3168 if (!spec->multi_io[idx].ctl_in)
3169 spec->multi_io[idx].ctl_in =
3170 snd_hda_codec_read(codec, nid, 0,
3171 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3172 if (output) {
3173 snd_hda_codec_update_cache(codec, nid, 0,
3174 AC_VERB_SET_PIN_WIDGET_CONTROL,
3175 PIN_OUT);
3176 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3177 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3178 HDA_AMP_MUTE, 0);
3179 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3180 } else {
3181 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3182 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3183 HDA_AMP_MUTE, HDA_AMP_MUTE);
3184 snd_hda_codec_update_cache(codec, nid, 0,
3185 AC_VERB_SET_PIN_WIDGET_CONTROL,
3186 spec->multi_io[idx].ctl_in);
3187 }
3188 return 0;
3189}
3190
3191static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3192 struct snd_ctl_elem_value *ucontrol)
3193{
3194 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3195 struct alc_spec *spec = codec->spec;
3196 int i, ch;
3197
3198 ch = ucontrol->value.enumerated.item[0];
3199 if (ch < 0 || ch > spec->multi_ios)
3200 return -EINVAL;
3201 if (ch == (spec->ext_channel_count - 1) / 2)
3202 return 0;
3203 spec->ext_channel_count = (ch + 1) * 2;
3204 for (i = 0; i < spec->multi_ios; i++)
3205 alc_set_multi_io(codec, i, i < ch);
3206 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003207 if (spec->need_dac_fix && !spec->const_channel_count)
3208 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003209 return 1;
3210}
3211
Takashi Iwaia9111322011-05-02 11:30:18 +02003212static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003213 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3214 .name = "Channel Mode",
3215 .info = alc_auto_ch_mode_info,
3216 .get = alc_auto_ch_mode_get,
3217 .put = alc_auto_ch_mode_put,
3218};
3219
Takashi Iwaicb053a82011-06-27 11:32:07 +02003220static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
3221 int (*fill_dac)(struct hda_codec *))
Takashi Iwaice764ab2011-04-27 16:35:23 +02003222{
3223 struct alc_spec *spec = codec->spec;
3224 struct auto_pin_cfg *cfg = &spec->autocfg;
3225 unsigned int location, defcfg;
3226 int num_pins;
3227
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003228 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3229 /* use HP as primary out */
3230 cfg->speaker_outs = cfg->line_outs;
3231 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3232 sizeof(cfg->speaker_pins));
3233 cfg->line_outs = cfg->hp_outs;
3234 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3235 cfg->hp_outs = 0;
3236 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3237 cfg->line_out_type = AUTO_PIN_HP_OUT;
Takashi Iwaicb053a82011-06-27 11:32:07 +02003238 if (fill_dac)
3239 fill_dac(codec);
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003240 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003241 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003242 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003243 return 0;
3244
3245 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3246 location = get_defcfg_location(defcfg);
3247
3248 num_pins = alc_auto_fill_multi_ios(codec, location);
3249 if (num_pins > 0) {
3250 struct snd_kcontrol_new *knew;
3251
3252 knew = alc_kcontrol_new(spec);
3253 if (!knew)
3254 return -ENOMEM;
3255 *knew = alc_auto_channel_mode_enum;
3256 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3257 if (!knew->name)
3258 return -ENOMEM;
3259
3260 spec->multi_ios = num_pins;
3261 spec->ext_channel_count = 2;
3262 spec->multiout.num_dacs = num_pins + 1;
3263 }
3264 return 0;
3265}
3266
Takashi Iwai1d045db2011-07-07 18:23:21 +02003267/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3268 * active input pins
3269 */
3270static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3271{
3272 struct alc_spec *spec = codec->spec;
3273 const struct hda_input_mux *imux;
3274 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3275 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3276 int i, n, nums;
3277
3278 imux = spec->input_mux;
3279 if (!imux)
3280 return;
3281 if (spec->dyn_adc_switch)
3282 return;
3283
3284 nums = 0;
3285 for (n = 0; n < spec->num_adc_nids; n++) {
3286 hda_nid_t cap = spec->private_capsrc_nids[n];
3287 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3288 for (i = 0; i < imux->num_items; i++) {
3289 hda_nid_t pin = spec->imux_pins[i];
3290 if (pin) {
3291 if (get_connection_index(codec, cap, pin) < 0)
3292 break;
3293 } else if (num_conns <= imux->items[i].index)
3294 break;
3295 }
3296 if (i >= imux->num_items) {
3297 adc_nids[nums] = spec->private_adc_nids[n];
3298 capsrc_nids[nums++] = cap;
3299 }
3300 }
3301 if (!nums) {
3302 /* check whether ADC-switch is possible */
3303 if (!alc_check_dyn_adc_switch(codec)) {
3304 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3305 " using fallback 0x%x\n",
3306 codec->chip_name, spec->private_adc_nids[0]);
3307 spec->num_adc_nids = 1;
3308 spec->auto_mic = 0;
3309 return;
3310 }
3311 } else if (nums != spec->num_adc_nids) {
3312 memcpy(spec->private_adc_nids, adc_nids,
3313 nums * sizeof(hda_nid_t));
3314 memcpy(spec->private_capsrc_nids, capsrc_nids,
3315 nums * sizeof(hda_nid_t));
3316 spec->num_adc_nids = nums;
3317 }
3318
3319 if (spec->auto_mic)
3320 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3321 else if (spec->input_mux->num_items == 1)
3322 spec->num_adc_nids = 1; /* reduce to a single ADC */
3323}
3324
3325/*
3326 * initialize ADC paths
3327 */
3328static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3329{
3330 struct alc_spec *spec = codec->spec;
3331 hda_nid_t nid;
3332
3333 nid = spec->adc_nids[adc_idx];
3334 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003335 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003336 snd_hda_codec_write(codec, nid, 0,
3337 AC_VERB_SET_AMP_GAIN_MUTE,
3338 AMP_IN_MUTE(0));
3339 return;
3340 }
3341 if (!spec->capsrc_nids)
3342 return;
3343 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003344 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003345 snd_hda_codec_write(codec, nid, 0,
3346 AC_VERB_SET_AMP_GAIN_MUTE,
3347 AMP_OUT_MUTE);
3348}
3349
3350static void alc_auto_init_input_src(struct hda_codec *codec)
3351{
3352 struct alc_spec *spec = codec->spec;
3353 int c, nums;
3354
3355 for (c = 0; c < spec->num_adc_nids; c++)
3356 alc_auto_init_adc(codec, c);
3357 if (spec->dyn_adc_switch)
3358 nums = 1;
3359 else
3360 nums = spec->num_adc_nids;
3361 for (c = 0; c < nums; c++)
3362 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3363}
3364
3365/* add mic boosts if needed */
3366static int alc_auto_add_mic_boost(struct hda_codec *codec)
3367{
3368 struct alc_spec *spec = codec->spec;
3369 struct auto_pin_cfg *cfg = &spec->autocfg;
3370 int i, err;
3371 int type_idx = 0;
3372 hda_nid_t nid;
3373 const char *prev_label = NULL;
3374
3375 for (i = 0; i < cfg->num_inputs; i++) {
3376 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3377 break;
3378 nid = cfg->inputs[i].pin;
3379 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3380 const char *label;
3381 char boost_label[32];
3382
3383 label = hda_get_autocfg_input_label(codec, cfg, i);
3384 if (prev_label && !strcmp(label, prev_label))
3385 type_idx++;
3386 else
3387 type_idx = 0;
3388 prev_label = label;
3389
3390 snprintf(boost_label, sizeof(boost_label),
3391 "%s Boost Volume", label);
3392 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3393 boost_label, type_idx,
3394 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3395 if (err < 0)
3396 return err;
3397 }
3398 }
3399 return 0;
3400}
3401
3402/* select or unmute the given capsrc route */
3403static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3404 int idx)
3405{
3406 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3407 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3408 HDA_AMP_MUTE, 0);
3409 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3410 snd_hda_codec_write_cache(codec, cap, 0,
3411 AC_VERB_SET_CONNECT_SEL, idx);
3412 }
3413}
3414
3415/* set the default connection to that pin */
3416static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3417{
3418 struct alc_spec *spec = codec->spec;
3419 int i;
3420
3421 if (!pin)
3422 return 0;
3423 for (i = 0; i < spec->num_adc_nids; i++) {
3424 hda_nid_t cap = spec->capsrc_nids ?
3425 spec->capsrc_nids[i] : spec->adc_nids[i];
3426 int idx;
3427
3428 idx = get_connection_index(codec, cap, pin);
3429 if (idx < 0)
3430 continue;
3431 select_or_unmute_capsrc(codec, cap, idx);
3432 return i; /* return the found index */
3433 }
3434 return -1; /* not found */
3435}
3436
3437/* initialize some special cases for input sources */
3438static void alc_init_special_input_src(struct hda_codec *codec)
3439{
3440 struct alc_spec *spec = codec->spec;
3441 int i;
3442
3443 for (i = 0; i < spec->autocfg.num_inputs; i++)
3444 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3445}
3446
3447/* assign appropriate capture mixers */
3448static void set_capture_mixer(struct hda_codec *codec)
3449{
3450 struct alc_spec *spec = codec->spec;
3451 static const struct snd_kcontrol_new *caps[2][3] = {
3452 { alc_capture_mixer_nosrc1,
3453 alc_capture_mixer_nosrc2,
3454 alc_capture_mixer_nosrc3 },
3455 { alc_capture_mixer1,
3456 alc_capture_mixer2,
3457 alc_capture_mixer3 },
3458 };
3459
3460 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003461 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003462 if (!spec->capsrc_nids)
3463 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003464 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003465 return; /* no volume in capsrc, too */
3466 spec->vol_in_capsrc = 1;
3467 }
3468
3469 if (spec->num_adc_nids > 0) {
3470 int mux = 0;
3471 int num_adcs = 0;
3472
3473 if (spec->input_mux && spec->input_mux->num_items > 1)
3474 mux = 1;
3475 if (spec->auto_mic) {
3476 num_adcs = 1;
3477 mux = 0;
3478 } else if (spec->dyn_adc_switch)
3479 num_adcs = 1;
3480 if (!num_adcs) {
3481 if (spec->num_adc_nids > 3)
3482 spec->num_adc_nids = 3;
3483 else if (!spec->num_adc_nids)
3484 return;
3485 num_adcs = spec->num_adc_nids;
3486 }
3487 spec->cap_mixer = caps[mux][num_adcs - 1];
3488 }
3489}
3490
3491/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003492 * standard auto-parser initializations
3493 */
3494static void alc_auto_init_std(struct hda_codec *codec)
3495{
3496 struct alc_spec *spec = codec->spec;
3497 alc_auto_init_multi_out(codec);
3498 alc_auto_init_extra_out(codec);
3499 alc_auto_init_analog_input(codec);
3500 alc_auto_init_input_src(codec);
3501 alc_auto_init_digital(codec);
3502 if (spec->unsol_event)
3503 alc_inithook(codec);
3504}
3505
3506/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003507 * Digital-beep handlers
3508 */
3509#ifdef CONFIG_SND_HDA_INPUT_BEEP
3510#define set_beep_amp(spec, nid, idx, dir) \
3511 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3512
3513static const struct snd_pci_quirk beep_white_list[] = {
3514 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3515 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3516 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3517 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3518 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3519 {}
3520};
3521
3522static inline int has_cdefine_beep(struct hda_codec *codec)
3523{
3524 struct alc_spec *spec = codec->spec;
3525 const struct snd_pci_quirk *q;
3526 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3527 if (q)
3528 return q->value;
3529 return spec->cdefine.enable_pcbeep;
3530}
3531#else
3532#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3533#define has_cdefine_beep(codec) 0
3534#endif
3535
3536/* parse the BIOS configuration and set up the alc_spec */
3537/* return 1 if successful, 0 if the proper config is not found,
3538 * or a negative error code
3539 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003540static int alc_parse_auto_config(struct hda_codec *codec,
3541 const hda_nid_t *ignore_nids,
3542 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003543{
3544 struct alc_spec *spec = codec->spec;
3545 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003546
3547 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003548 ignore_nids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003549 if (err < 0)
3550 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003551 if (!spec->autocfg.line_outs) {
3552 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
3553 spec->multiout.max_channels = 2;
3554 spec->no_analog = 1;
3555 goto dig_only;
3556 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003557 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003558 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003559 err = alc_auto_fill_dac_nids(codec);
3560 if (err < 0)
3561 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003562 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
3563 if (err < 0)
3564 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003565 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
3566 if (err < 0)
3567 return err;
3568 err = alc_auto_create_hp_out(codec);
3569 if (err < 0)
3570 return err;
3571 err = alc_auto_create_speaker_out(codec);
3572 if (err < 0)
3573 return err;
3574 err = alc_auto_create_input_ctls(codec);
3575 if (err < 0)
3576 return err;
3577
3578 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3579
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003580 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02003581 alc_auto_parse_digital(codec);
3582
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003583 if (!spec->no_analog)
3584 alc_remove_invalid_adc_nids(codec);
3585
3586 if (ssid_nids)
3587 alc_ssid_check(codec, ssid_nids);
3588
3589 if (!spec->no_analog) {
3590 alc_auto_check_switches(codec);
3591 err = alc_auto_add_mic_boost(codec);
3592 if (err < 0)
3593 return err;
3594 }
3595
Takashi Iwai1d045db2011-07-07 18:23:21 +02003596 if (spec->kctls.list)
3597 add_mixer(spec, spec->kctls.list);
3598
Takashi Iwai1d045db2011-07-07 18:23:21 +02003599 return 1;
3600}
3601
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003602static int alc880_parse_auto_config(struct hda_codec *codec)
3603{
3604 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3605 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3606 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
3607}
3608
Takashi Iwai1d045db2011-07-07 18:23:21 +02003609#ifdef CONFIG_SND_HDA_POWER_SAVE
3610static const struct hda_amp_list alc880_loopbacks[] = {
3611 { 0x0b, HDA_INPUT, 0 },
3612 { 0x0b, HDA_INPUT, 1 },
3613 { 0x0b, HDA_INPUT, 2 },
3614 { 0x0b, HDA_INPUT, 3 },
3615 { 0x0b, HDA_INPUT, 4 },
3616 { } /* end */
3617};
3618#endif
3619
3620/*
3621 * board setups
3622 */
3623#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3624#define alc_board_config \
3625 snd_hda_check_board_config
3626#define alc_board_codec_sid_config \
3627 snd_hda_check_board_codec_sid_config
3628#include "alc_quirks.c"
3629#else
3630#define alc_board_config(codec, nums, models, tbl) -1
3631#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3632#define setup_preset(codec, x) /* NOP */
3633#endif
3634
3635/*
3636 * OK, here we have finally the patch for ALC880
3637 */
3638#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3639#include "alc880_quirks.c"
3640#endif
3641
3642static int patch_alc880(struct hda_codec *codec)
3643{
3644 struct alc_spec *spec;
3645 int board_config;
3646 int err;
3647
3648 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3649 if (spec == NULL)
3650 return -ENOMEM;
3651
3652 codec->spec = spec;
3653
3654 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003655 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003656
3657 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3658 alc880_models, alc880_cfg_tbl);
3659 if (board_config < 0) {
3660 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3661 codec->chip_name);
3662 board_config = ALC_MODEL_AUTO;
3663 }
3664
3665 if (board_config == ALC_MODEL_AUTO) {
3666 /* automatic parse from the BIOS config */
3667 err = alc880_parse_auto_config(codec);
3668 if (err < 0) {
3669 alc_free(codec);
3670 return err;
3671 }
3672#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3673 else if (!err) {
3674 printk(KERN_INFO
3675 "hda_codec: Cannot set up configuration "
3676 "from BIOS. Using 3-stack mode...\n");
3677 board_config = ALC880_3ST;
3678 }
3679#endif
3680 }
3681
Takashi Iwai1d045db2011-07-07 18:23:21 +02003682 if (board_config != ALC_MODEL_AUTO)
3683 setup_preset(codec, &alc880_presets[board_config]);
3684
Takashi Iwai60a6a842011-07-27 14:01:24 +02003685 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003686 alc_auto_fill_adc_caps(codec);
3687 alc_rebuild_imux_for_auto_mic(codec);
3688 alc_remove_invalid_adc_nids(codec);
3689 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003690
3691 if (!spec->no_analog && !spec->cap_mixer)
3692 set_capture_mixer(codec);
3693
3694 if (!spec->no_analog) {
3695 err = snd_hda_attach_beep_device(codec, 0x1);
3696 if (err < 0) {
3697 alc_free(codec);
3698 return err;
3699 }
3700 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3701 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003702
3703 spec->vmaster_nid = 0x0c;
3704
3705 codec->patch_ops = alc_patch_ops;
3706 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003707 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003708#ifdef CONFIG_SND_HDA_POWER_SAVE
3709 if (!spec->loopback.amplist)
3710 spec->loopback.amplist = alc880_loopbacks;
3711#endif
3712
3713 return 0;
3714}
3715
3716
3717/*
3718 * ALC260 support
3719 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003720static int alc260_parse_auto_config(struct hda_codec *codec)
3721{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003722 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003723 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
3724 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003725}
3726
Takashi Iwai1d045db2011-07-07 18:23:21 +02003727#ifdef CONFIG_SND_HDA_POWER_SAVE
3728static const struct hda_amp_list alc260_loopbacks[] = {
3729 { 0x07, HDA_INPUT, 0 },
3730 { 0x07, HDA_INPUT, 1 },
3731 { 0x07, HDA_INPUT, 2 },
3732 { 0x07, HDA_INPUT, 3 },
3733 { 0x07, HDA_INPUT, 4 },
3734 { } /* end */
3735};
3736#endif
3737
3738/*
3739 * Pin config fixes
3740 */
3741enum {
3742 PINFIX_HP_DC5750,
3743};
3744
3745static const struct alc_fixup alc260_fixups[] = {
3746 [PINFIX_HP_DC5750] = {
3747 .type = ALC_FIXUP_PINS,
3748 .v.pins = (const struct alc_pincfg[]) {
3749 { 0x11, 0x90130110 }, /* speaker */
3750 { }
3751 }
3752 },
3753};
3754
3755static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3756 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3757 {}
3758};
3759
3760/*
3761 */
3762#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3763#include "alc260_quirks.c"
3764#endif
3765
3766static int patch_alc260(struct hda_codec *codec)
3767{
3768 struct alc_spec *spec;
3769 int err, board_config;
3770
3771 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3772 if (spec == NULL)
3773 return -ENOMEM;
3774
3775 codec->spec = spec;
3776
3777 spec->mixer_nid = 0x07;
3778
3779 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3780 alc260_models, alc260_cfg_tbl);
3781 if (board_config < 0) {
3782 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3783 codec->chip_name);
3784 board_config = ALC_MODEL_AUTO;
3785 }
3786
3787 if (board_config == ALC_MODEL_AUTO) {
3788 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3789 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3790 }
3791
3792 if (board_config == ALC_MODEL_AUTO) {
3793 /* automatic parse from the BIOS config */
3794 err = alc260_parse_auto_config(codec);
3795 if (err < 0) {
3796 alc_free(codec);
3797 return err;
3798 }
3799#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3800 else if (!err) {
3801 printk(KERN_INFO
3802 "hda_codec: Cannot set up configuration "
3803 "from BIOS. Using base mode...\n");
3804 board_config = ALC260_BASIC;
3805 }
3806#endif
3807 }
3808
Takashi Iwai1d045db2011-07-07 18:23:21 +02003809 if (board_config != ALC_MODEL_AUTO)
3810 setup_preset(codec, &alc260_presets[board_config]);
3811
Takashi Iwai60a6a842011-07-27 14:01:24 +02003812 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003813 alc_auto_fill_adc_caps(codec);
3814 alc_rebuild_imux_for_auto_mic(codec);
3815 alc_remove_invalid_adc_nids(codec);
3816 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003817
3818 if (!spec->no_analog && !spec->cap_mixer)
3819 set_capture_mixer(codec);
3820
3821 if (!spec->no_analog) {
3822 err = snd_hda_attach_beep_device(codec, 0x1);
3823 if (err < 0) {
3824 alc_free(codec);
3825 return err;
3826 }
3827 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3828 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003829
3830 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3831
3832 spec->vmaster_nid = 0x08;
3833
3834 codec->patch_ops = alc_patch_ops;
3835 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02003836 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003837 spec->shutup = alc_eapd_shutup;
3838#ifdef CONFIG_SND_HDA_POWER_SAVE
3839 if (!spec->loopback.amplist)
3840 spec->loopback.amplist = alc260_loopbacks;
3841#endif
3842
3843 return 0;
3844}
3845
3846
3847/*
3848 * ALC882/883/885/888/889 support
3849 *
3850 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3851 * configuration. Each pin widget can choose any input DACs and a mixer.
3852 * Each ADC is connected from a mixer of all inputs. This makes possible
3853 * 6-channel independent captures.
3854 *
3855 * In addition, an independent DAC for the multi-playback (not used in this
3856 * driver yet).
3857 */
3858#ifdef CONFIG_SND_HDA_POWER_SAVE
3859#define alc882_loopbacks alc880_loopbacks
3860#endif
3861
3862/*
3863 * Pin config fixes
3864 */
3865enum {
3866 PINFIX_ABIT_AW9D_MAX,
3867 PINFIX_LENOVO_Y530,
3868 PINFIX_PB_M5210,
3869 PINFIX_ACER_ASPIRE_7736,
3870};
3871
3872static const struct alc_fixup alc882_fixups[] = {
3873 [PINFIX_ABIT_AW9D_MAX] = {
3874 .type = ALC_FIXUP_PINS,
3875 .v.pins = (const struct alc_pincfg[]) {
3876 { 0x15, 0x01080104 }, /* side */
3877 { 0x16, 0x01011012 }, /* rear */
3878 { 0x17, 0x01016011 }, /* clfe */
3879 { }
3880 }
3881 },
3882 [PINFIX_LENOVO_Y530] = {
3883 .type = ALC_FIXUP_PINS,
3884 .v.pins = (const struct alc_pincfg[]) {
3885 { 0x15, 0x99130112 }, /* rear int speakers */
3886 { 0x16, 0x99130111 }, /* subwoofer */
3887 { }
3888 }
3889 },
3890 [PINFIX_PB_M5210] = {
3891 .type = ALC_FIXUP_VERBS,
3892 .v.verbs = (const struct hda_verb[]) {
3893 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
3894 {}
3895 }
3896 },
3897 [PINFIX_ACER_ASPIRE_7736] = {
3898 .type = ALC_FIXUP_SKU,
3899 .v.sku = ALC_FIXUP_SKU_IGNORE,
3900 },
3901};
3902
3903static const struct snd_pci_quirk alc882_fixup_tbl[] = {
3904 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
3905 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
3906 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
3907 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
3908 {}
3909};
3910
3911/*
3912 * BIOS auto configuration
3913 */
3914/* almost identical with ALC880 parser... */
3915static int alc882_parse_auto_config(struct hda_codec *codec)
3916{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003917 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003918 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3919 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003920}
3921
Takashi Iwai1d045db2011-07-07 18:23:21 +02003922/*
3923 */
3924#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3925#include "alc882_quirks.c"
3926#endif
3927
3928static int patch_alc882(struct hda_codec *codec)
3929{
3930 struct alc_spec *spec;
3931 int err, board_config;
3932
3933 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3934 if (spec == NULL)
3935 return -ENOMEM;
3936
3937 codec->spec = spec;
3938
3939 spec->mixer_nid = 0x0b;
3940
3941 switch (codec->vendor_id) {
3942 case 0x10ec0882:
3943 case 0x10ec0885:
3944 break;
3945 default:
3946 /* ALC883 and variants */
3947 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
3948 break;
3949 }
3950
3951 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
3952 alc882_models, alc882_cfg_tbl);
3953
3954 if (board_config < 0)
3955 board_config = alc_board_codec_sid_config(codec,
3956 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
3957
3958 if (board_config < 0) {
3959 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3960 codec->chip_name);
3961 board_config = ALC_MODEL_AUTO;
3962 }
3963
3964 if (board_config == ALC_MODEL_AUTO) {
3965 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
3966 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3967 }
3968
3969 alc_auto_parse_customize_define(codec);
3970
3971 if (board_config == ALC_MODEL_AUTO) {
3972 /* automatic parse from the BIOS config */
3973 err = alc882_parse_auto_config(codec);
3974 if (err < 0) {
3975 alc_free(codec);
3976 return err;
3977 }
3978#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3979 else if (!err) {
3980 printk(KERN_INFO
3981 "hda_codec: Cannot set up configuration "
3982 "from BIOS. Using base mode...\n");
3983 board_config = ALC882_3ST_DIG;
3984 }
3985#endif
3986 }
3987
Takashi Iwai1d045db2011-07-07 18:23:21 +02003988 if (board_config != ALC_MODEL_AUTO)
3989 setup_preset(codec, &alc882_presets[board_config]);
3990
Takashi Iwai60a6a842011-07-27 14:01:24 +02003991 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003992 alc_auto_fill_adc_caps(codec);
3993 alc_rebuild_imux_for_auto_mic(codec);
3994 alc_remove_invalid_adc_nids(codec);
3995 }
3996
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003997 if (!spec->no_analog && !spec->cap_mixer)
3998 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003999
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004000 if (!spec->no_analog && has_cdefine_beep(codec)) {
4001 err = snd_hda_attach_beep_device(codec, 0x1);
4002 if (err < 0) {
4003 alc_free(codec);
4004 return err;
4005 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004006 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004007 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004008
4009 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4010
4011 spec->vmaster_nid = 0x0c;
4012
4013 codec->patch_ops = alc_patch_ops;
4014 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004015 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004016
4017 alc_init_jacks(codec);
4018#ifdef CONFIG_SND_HDA_POWER_SAVE
4019 if (!spec->loopback.amplist)
4020 spec->loopback.amplist = alc882_loopbacks;
4021#endif
4022
4023 return 0;
4024}
4025
4026
4027/*
4028 * ALC262 support
4029 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004030static int alc262_parse_auto_config(struct hda_codec *codec)
4031{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004032 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004033 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4034 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004035}
4036
4037/*
4038 * Pin config fixes
4039 */
4040enum {
4041 PINFIX_FSC_H270,
4042 PINFIX_HP_Z200,
4043};
4044
4045static const struct alc_fixup alc262_fixups[] = {
4046 [PINFIX_FSC_H270] = {
4047 .type = ALC_FIXUP_PINS,
4048 .v.pins = (const struct alc_pincfg[]) {
4049 { 0x14, 0x99130110 }, /* speaker */
4050 { 0x15, 0x0221142f }, /* front HP */
4051 { 0x1b, 0x0121141f }, /* rear HP */
4052 { }
4053 }
4054 },
4055 [PINFIX_HP_Z200] = {
4056 .type = ALC_FIXUP_PINS,
4057 .v.pins = (const struct alc_pincfg[]) {
4058 { 0x16, 0x99130120 }, /* internal speaker */
4059 { }
4060 }
4061 },
4062};
4063
4064static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4065 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4066 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4067 {}
4068};
4069
4070
4071#ifdef CONFIG_SND_HDA_POWER_SAVE
4072#define alc262_loopbacks alc880_loopbacks
4073#endif
4074
Takashi Iwai1d045db2011-07-07 18:23:21 +02004075/*
4076 */
4077#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4078#include "alc262_quirks.c"
4079#endif
4080
4081static int patch_alc262(struct hda_codec *codec)
4082{
4083 struct alc_spec *spec;
4084 int board_config;
4085 int err;
4086
4087 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4088 if (spec == NULL)
4089 return -ENOMEM;
4090
4091 codec->spec = spec;
4092
4093 spec->mixer_nid = 0x0b;
4094
4095#if 0
4096 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4097 * under-run
4098 */
4099 {
4100 int tmp;
4101 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4102 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4103 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4104 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4105 }
4106#endif
4107 alc_auto_parse_customize_define(codec);
4108
4109 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4110
4111 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4112 alc262_models, alc262_cfg_tbl);
4113
4114 if (board_config < 0) {
4115 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4116 codec->chip_name);
4117 board_config = ALC_MODEL_AUTO;
4118 }
4119
4120 if (board_config == ALC_MODEL_AUTO) {
4121 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4122 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4123 }
4124
4125 if (board_config == ALC_MODEL_AUTO) {
4126 /* automatic parse from the BIOS config */
4127 err = alc262_parse_auto_config(codec);
4128 if (err < 0) {
4129 alc_free(codec);
4130 return err;
4131 }
4132#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4133 else if (!err) {
4134 printk(KERN_INFO
4135 "hda_codec: Cannot set up configuration "
4136 "from BIOS. Using base mode...\n");
4137 board_config = ALC262_BASIC;
4138 }
4139#endif
4140 }
4141
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004142 if (board_config != ALC_MODEL_AUTO)
4143 setup_preset(codec, &alc262_presets[board_config]);
4144
Takashi Iwai60a6a842011-07-27 14:01:24 +02004145 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004146 alc_auto_fill_adc_caps(codec);
4147 alc_rebuild_imux_for_auto_mic(codec);
4148 alc_remove_invalid_adc_nids(codec);
4149 }
4150
4151 if (!spec->no_analog && !spec->cap_mixer)
4152 set_capture_mixer(codec);
4153
Takashi Iwai1d045db2011-07-07 18:23:21 +02004154 if (!spec->no_analog && has_cdefine_beep(codec)) {
4155 err = snd_hda_attach_beep_device(codec, 0x1);
4156 if (err < 0) {
4157 alc_free(codec);
4158 return err;
4159 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004160 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004161 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004162
4163 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4164
4165 spec->vmaster_nid = 0x0c;
4166
4167 codec->patch_ops = alc_patch_ops;
4168 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004169 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004170 spec->shutup = alc_eapd_shutup;
4171
4172 alc_init_jacks(codec);
4173#ifdef CONFIG_SND_HDA_POWER_SAVE
4174 if (!spec->loopback.amplist)
4175 spec->loopback.amplist = alc262_loopbacks;
4176#endif
4177
4178 return 0;
4179}
4180
4181/*
4182 * ALC268
4183 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004184/* bind Beep switches of both NID 0x0f and 0x10 */
4185static const struct hda_bind_ctls alc268_bind_beep_sw = {
4186 .ops = &snd_hda_bind_sw,
4187 .values = {
4188 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4189 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4190 0
4191 },
4192};
4193
4194static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4195 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4196 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4197 { }
4198};
4199
4200/* set PCBEEP vol = 0, mute connections */
4201static const struct hda_verb alc268_beep_init_verbs[] = {
4202 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4203 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4204 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4205 { }
4206};
4207
4208/*
4209 * BIOS auto configuration
4210 */
4211static int alc268_parse_auto_config(struct hda_codec *codec)
4212{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004213 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004214 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004215 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4216 if (err > 0) {
4217 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4218 add_mixer(spec, alc268_beep_mixer);
4219 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004220 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004221 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004222 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004223}
4224
Takashi Iwai1d045db2011-07-07 18:23:21 +02004225/*
4226 */
4227#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4228#include "alc268_quirks.c"
4229#endif
4230
4231static int patch_alc268(struct hda_codec *codec)
4232{
4233 struct alc_spec *spec;
4234 int board_config;
4235 int i, has_beep, err;
4236
4237 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4238 if (spec == NULL)
4239 return -ENOMEM;
4240
4241 codec->spec = spec;
4242
4243 /* ALC268 has no aa-loopback mixer */
4244
4245 board_config = alc_board_config(codec, ALC268_MODEL_LAST,
4246 alc268_models, alc268_cfg_tbl);
4247
4248 if (board_config < 0)
4249 board_config = alc_board_codec_sid_config(codec,
4250 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
4251
4252 if (board_config < 0) {
4253 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4254 codec->chip_name);
4255 board_config = ALC_MODEL_AUTO;
4256 }
4257
4258 if (board_config == ALC_MODEL_AUTO) {
4259 /* automatic parse from the BIOS config */
4260 err = alc268_parse_auto_config(codec);
4261 if (err < 0) {
4262 alc_free(codec);
4263 return err;
4264 }
4265#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4266 else if (!err) {
4267 printk(KERN_INFO
4268 "hda_codec: Cannot set up configuration "
4269 "from BIOS. Using base mode...\n");
4270 board_config = ALC268_3ST;
4271 }
4272#endif
4273 }
4274
4275 if (board_config != ALC_MODEL_AUTO)
4276 setup_preset(codec, &alc268_presets[board_config]);
4277
4278 has_beep = 0;
4279 for (i = 0; i < spec->num_mixers; i++) {
4280 if (spec->mixers[i] == alc268_beep_mixer) {
4281 has_beep = 1;
4282 break;
4283 }
4284 }
4285
4286 if (has_beep) {
4287 err = snd_hda_attach_beep_device(codec, 0x1);
4288 if (err < 0) {
4289 alc_free(codec);
4290 return err;
4291 }
4292 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4293 /* override the amp caps for beep generator */
4294 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4295 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4296 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4297 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4298 (0 << AC_AMPCAP_MUTE_SHIFT));
4299 }
4300
Takashi Iwai60a6a842011-07-27 14:01:24 +02004301 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004302 alc_auto_fill_adc_caps(codec);
4303 alc_rebuild_imux_for_auto_mic(codec);
4304 alc_remove_invalid_adc_nids(codec);
4305 }
4306
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004307 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004308 set_capture_mixer(codec);
4309
4310 spec->vmaster_nid = 0x02;
4311
4312 codec->patch_ops = alc_patch_ops;
4313 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004314 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004315 spec->shutup = alc_eapd_shutup;
4316
4317 alc_init_jacks(codec);
4318
4319 return 0;
4320}
4321
4322/*
4323 * ALC269
4324 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004325#ifdef CONFIG_SND_HDA_POWER_SAVE
4326#define alc269_loopbacks alc880_loopbacks
4327#endif
4328
4329static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4330 .substreams = 1,
4331 .channels_min = 2,
4332 .channels_max = 8,
4333 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4334 /* NID is set in alc_build_pcms */
4335 .ops = {
4336 .open = alc_playback_pcm_open,
4337 .prepare = alc_playback_pcm_prepare,
4338 .cleanup = alc_playback_pcm_cleanup
4339 },
4340};
4341
4342static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4343 .substreams = 1,
4344 .channels_min = 2,
4345 .channels_max = 2,
4346 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4347 /* NID is set in alc_build_pcms */
4348};
4349
4350#ifdef CONFIG_SND_HDA_POWER_SAVE
4351static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4352{
4353 switch (codec->subsystem_id) {
4354 case 0x103c1586:
4355 return 1;
4356 }
4357 return 0;
4358}
4359
4360static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4361{
4362 /* update mute-LED according to the speaker mute state */
4363 if (nid == 0x01 || nid == 0x14) {
4364 int pinval;
4365 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4366 HDA_AMP_MUTE)
4367 pinval = 0x24;
4368 else
4369 pinval = 0x20;
4370 /* mic2 vref pin is used for mute LED control */
4371 snd_hda_codec_update_cache(codec, 0x19, 0,
4372 AC_VERB_SET_PIN_WIDGET_CONTROL,
4373 pinval);
4374 }
4375 return alc_check_power_status(codec, nid);
4376}
4377#endif /* CONFIG_SND_HDA_POWER_SAVE */
4378
4379/* different alc269-variants */
4380enum {
4381 ALC269_TYPE_ALC269VA,
4382 ALC269_TYPE_ALC269VB,
4383 ALC269_TYPE_ALC269VC,
4384};
4385
4386/*
4387 * BIOS auto configuration
4388 */
4389static int alc269_parse_auto_config(struct hda_codec *codec)
4390{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004391 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004392 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
4393 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4394 struct alc_spec *spec = codec->spec;
4395 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
4396 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004397
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004398 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004399}
4400
Takashi Iwai1d045db2011-07-07 18:23:21 +02004401static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4402{
4403 int val = alc_read_coef_idx(codec, 0x04);
4404 if (power_up)
4405 val |= 1 << 11;
4406 else
4407 val &= ~(1 << 11);
4408 alc_write_coef_idx(codec, 0x04, val);
4409}
4410
4411static void alc269_shutup(struct hda_codec *codec)
4412{
4413 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4414 alc269_toggle_power_output(codec, 0);
4415 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4416 alc269_toggle_power_output(codec, 0);
4417 msleep(150);
4418 }
4419}
4420
Takashi Iwai2a439522011-07-26 09:52:50 +02004421#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004422static int alc269_resume(struct hda_codec *codec)
4423{
4424 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4425 alc269_toggle_power_output(codec, 0);
4426 msleep(150);
4427 }
4428
4429 codec->patch_ops.init(codec);
4430
4431 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4432 alc269_toggle_power_output(codec, 1);
4433 msleep(200);
4434 }
4435
4436 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4437 alc269_toggle_power_output(codec, 1);
4438
4439 snd_hda_codec_resume_amp(codec);
4440 snd_hda_codec_resume_cache(codec);
4441 hda_call_check_power_status(codec, 0x01);
4442 return 0;
4443}
Takashi Iwai2a439522011-07-26 09:52:50 +02004444#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004445
4446static void alc269_fixup_hweq(struct hda_codec *codec,
4447 const struct alc_fixup *fix, int action)
4448{
4449 int coef;
4450
4451 if (action != ALC_FIXUP_ACT_INIT)
4452 return;
4453 coef = alc_read_coef_idx(codec, 0x1e);
4454 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4455}
4456
4457static void alc271_fixup_dmic(struct hda_codec *codec,
4458 const struct alc_fixup *fix, int action)
4459{
4460 static const struct hda_verb verbs[] = {
4461 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4462 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4463 {}
4464 };
4465 unsigned int cfg;
4466
4467 if (strcmp(codec->chip_name, "ALC271X"))
4468 return;
4469 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4470 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4471 snd_hda_sequence_write(codec, verbs);
4472}
4473
Takashi Iwai017f2a12011-07-09 14:42:25 +02004474static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4475 const struct alc_fixup *fix, int action)
4476{
4477 struct alc_spec *spec = codec->spec;
4478
4479 if (action != ALC_FIXUP_ACT_PROBE)
4480 return;
4481
4482 /* Due to a hardware problem on Lenovo Ideadpad, we need to
4483 * fix the sample rate of analog I/O to 44.1kHz
4484 */
4485 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
4486 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4487}
4488
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004489static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4490 const struct alc_fixup *fix, int action)
4491{
4492 int coef;
4493
4494 if (action != ALC_FIXUP_ACT_INIT)
4495 return;
4496 /* The digital-mic unit sends PDM (differential signal) instead of
4497 * the standard PCM, thus you can't record a valid mono stream as is.
4498 * Below is a workaround specific to ALC269 to control the dmic
4499 * signal source as mono.
4500 */
4501 coef = alc_read_coef_idx(codec, 0x07);
4502 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4503}
4504
Takashi Iwai1d045db2011-07-07 18:23:21 +02004505enum {
4506 ALC269_FIXUP_SONY_VAIO,
4507 ALC275_FIXUP_SONY_VAIO_GPIO2,
4508 ALC269_FIXUP_DELL_M101Z,
4509 ALC269_FIXUP_SKU_IGNORE,
4510 ALC269_FIXUP_ASUS_G73JW,
4511 ALC269_FIXUP_LENOVO_EAPD,
4512 ALC275_FIXUP_SONY_HWEQ,
4513 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004514 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004515 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004516};
4517
4518static const struct alc_fixup alc269_fixups[] = {
4519 [ALC269_FIXUP_SONY_VAIO] = {
4520 .type = ALC_FIXUP_VERBS,
4521 .v.verbs = (const struct hda_verb[]) {
4522 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4523 {}
4524 }
4525 },
4526 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4527 .type = ALC_FIXUP_VERBS,
4528 .v.verbs = (const struct hda_verb[]) {
4529 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4530 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4531 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4532 { }
4533 },
4534 .chained = true,
4535 .chain_id = ALC269_FIXUP_SONY_VAIO
4536 },
4537 [ALC269_FIXUP_DELL_M101Z] = {
4538 .type = ALC_FIXUP_VERBS,
4539 .v.verbs = (const struct hda_verb[]) {
4540 /* Enables internal speaker */
4541 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4542 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4543 {}
4544 }
4545 },
4546 [ALC269_FIXUP_SKU_IGNORE] = {
4547 .type = ALC_FIXUP_SKU,
4548 .v.sku = ALC_FIXUP_SKU_IGNORE,
4549 },
4550 [ALC269_FIXUP_ASUS_G73JW] = {
4551 .type = ALC_FIXUP_PINS,
4552 .v.pins = (const struct alc_pincfg[]) {
4553 { 0x17, 0x99130111 }, /* subwoofer */
4554 { }
4555 }
4556 },
4557 [ALC269_FIXUP_LENOVO_EAPD] = {
4558 .type = ALC_FIXUP_VERBS,
4559 .v.verbs = (const struct hda_verb[]) {
4560 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4561 {}
4562 }
4563 },
4564 [ALC275_FIXUP_SONY_HWEQ] = {
4565 .type = ALC_FIXUP_FUNC,
4566 .v.func = alc269_fixup_hweq,
4567 .chained = true,
4568 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4569 },
4570 [ALC271_FIXUP_DMIC] = {
4571 .type = ALC_FIXUP_FUNC,
4572 .v.func = alc271_fixup_dmic,
4573 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004574 [ALC269_FIXUP_PCM_44K] = {
4575 .type = ALC_FIXUP_FUNC,
4576 .v.func = alc269_fixup_pcm_44k,
4577 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004578 [ALC269_FIXUP_STEREO_DMIC] = {
4579 .type = ALC_FIXUP_FUNC,
4580 .v.func = alc269_fixup_stereo_dmic,
4581 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004582};
4583
4584static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02004585 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004586 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4587 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4588 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4589 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4590 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004591 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4592 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4593 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4594 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4595 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4596 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
4597 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4598 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4599 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4600 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4601 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02004602 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004603 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
4604 {}
4605};
4606
4607
4608static int alc269_fill_coef(struct hda_codec *codec)
4609{
4610 int val;
4611
4612 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4613 alc_write_coef_idx(codec, 0xf, 0x960b);
4614 alc_write_coef_idx(codec, 0xe, 0x8817);
4615 }
4616
4617 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4618 alc_write_coef_idx(codec, 0xf, 0x960b);
4619 alc_write_coef_idx(codec, 0xe, 0x8814);
4620 }
4621
4622 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4623 val = alc_read_coef_idx(codec, 0x04);
4624 /* Power up output pin */
4625 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4626 }
4627
4628 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4629 val = alc_read_coef_idx(codec, 0xd);
4630 if ((val & 0x0c00) >> 10 != 0x1) {
4631 /* Capless ramp up clock control */
4632 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4633 }
4634 val = alc_read_coef_idx(codec, 0x17);
4635 if ((val & 0x01c0) >> 6 != 0x4) {
4636 /* Class D power on reset */
4637 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4638 }
4639 }
4640
4641 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4642 alc_write_coef_idx(codec, 0xd, val | (1<<14));
4643
4644 val = alc_read_coef_idx(codec, 0x4); /* HP */
4645 alc_write_coef_idx(codec, 0x4, val | (1<<11));
4646
4647 return 0;
4648}
4649
4650/*
4651 */
4652#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4653#include "alc269_quirks.c"
4654#endif
4655
4656static int patch_alc269(struct hda_codec *codec)
4657{
4658 struct alc_spec *spec;
4659 int board_config, coef;
4660 int err;
4661
4662 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4663 if (spec == NULL)
4664 return -ENOMEM;
4665
4666 codec->spec = spec;
4667
4668 spec->mixer_nid = 0x0b;
4669
4670 alc_auto_parse_customize_define(codec);
4671
4672 if (codec->vendor_id == 0x10ec0269) {
4673 spec->codec_variant = ALC269_TYPE_ALC269VA;
4674 coef = alc_read_coef_idx(codec, 0);
4675 if ((coef & 0x00f0) == 0x0010) {
4676 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
4677 spec->cdefine.platform_type == 1) {
4678 alc_codec_rename(codec, "ALC271X");
4679 } else if ((coef & 0xf000) == 0x2000) {
4680 alc_codec_rename(codec, "ALC259");
4681 } else if ((coef & 0xf000) == 0x3000) {
4682 alc_codec_rename(codec, "ALC258");
4683 } else if ((coef & 0xfff0) == 0x3010) {
4684 alc_codec_rename(codec, "ALC277");
4685 } else {
4686 alc_codec_rename(codec, "ALC269VB");
4687 }
4688 spec->codec_variant = ALC269_TYPE_ALC269VB;
4689 } else if ((coef & 0x00f0) == 0x0020) {
4690 if (coef == 0xa023)
4691 alc_codec_rename(codec, "ALC259");
4692 else if (coef == 0x6023)
4693 alc_codec_rename(codec, "ALC281X");
4694 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4695 codec->bus->pci->subsystem_device == 0x21f3)
4696 alc_codec_rename(codec, "ALC3202");
4697 else
4698 alc_codec_rename(codec, "ALC269VC");
4699 spec->codec_variant = ALC269_TYPE_ALC269VC;
4700 } else
4701 alc_fix_pll_init(codec, 0x20, 0x04, 15);
4702 alc269_fill_coef(codec);
4703 }
4704
4705 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
4706 alc269_models, alc269_cfg_tbl);
4707
4708 if (board_config < 0) {
4709 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4710 codec->chip_name);
4711 board_config = ALC_MODEL_AUTO;
4712 }
4713
4714 if (board_config == ALC_MODEL_AUTO) {
4715 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
4716 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4717 }
4718
4719 if (board_config == ALC_MODEL_AUTO) {
4720 /* automatic parse from the BIOS config */
4721 err = alc269_parse_auto_config(codec);
4722 if (err < 0) {
4723 alc_free(codec);
4724 return err;
4725 }
4726#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4727 else if (!err) {
4728 printk(KERN_INFO
4729 "hda_codec: Cannot set up configuration "
4730 "from BIOS. Using base mode...\n");
4731 board_config = ALC269_BASIC;
4732 }
4733#endif
4734 }
4735
Takashi Iwai1d045db2011-07-07 18:23:21 +02004736 if (board_config != ALC_MODEL_AUTO)
4737 setup_preset(codec, &alc269_presets[board_config]);
4738
Takashi Iwai60a6a842011-07-27 14:01:24 +02004739 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004740 alc_auto_fill_adc_caps(codec);
4741 alc_rebuild_imux_for_auto_mic(codec);
4742 alc_remove_invalid_adc_nids(codec);
4743 }
4744
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004745 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004746 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004747
4748 if (!spec->no_analog && has_cdefine_beep(codec)) {
4749 err = snd_hda_attach_beep_device(codec, 0x1);
4750 if (err < 0) {
4751 alc_free(codec);
4752 return err;
4753 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004754 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004755 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004756
4757 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4758
4759 spec->vmaster_nid = 0x02;
4760
4761 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02004762#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004763 codec->patch_ops.resume = alc269_resume;
4764#endif
4765 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004766 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004767 spec->shutup = alc269_shutup;
4768
4769 alc_init_jacks(codec);
4770#ifdef CONFIG_SND_HDA_POWER_SAVE
4771 if (!spec->loopback.amplist)
4772 spec->loopback.amplist = alc269_loopbacks;
4773 if (alc269_mic2_for_mute_led(codec))
4774 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
4775#endif
4776
4777 return 0;
4778}
4779
4780/*
4781 * ALC861
4782 */
4783
Takashi Iwai1d045db2011-07-07 18:23:21 +02004784static int alc861_parse_auto_config(struct hda_codec *codec)
4785{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004786 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004787 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4788 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004789}
4790
Takashi Iwai1d045db2011-07-07 18:23:21 +02004791#ifdef CONFIG_SND_HDA_POWER_SAVE
4792static const struct hda_amp_list alc861_loopbacks[] = {
4793 { 0x15, HDA_INPUT, 0 },
4794 { 0x15, HDA_INPUT, 1 },
4795 { 0x15, HDA_INPUT, 2 },
4796 { 0x15, HDA_INPUT, 3 },
4797 { } /* end */
4798};
4799#endif
4800
4801
4802/* Pin config fixes */
4803enum {
4804 PINFIX_FSC_AMILO_PI1505,
4805};
4806
4807static const struct alc_fixup alc861_fixups[] = {
4808 [PINFIX_FSC_AMILO_PI1505] = {
4809 .type = ALC_FIXUP_PINS,
4810 .v.pins = (const struct alc_pincfg[]) {
4811 { 0x0b, 0x0221101f }, /* HP */
4812 { 0x0f, 0x90170310 }, /* speaker */
4813 { }
4814 }
4815 },
4816};
4817
4818static const struct snd_pci_quirk alc861_fixup_tbl[] = {
4819 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
4820 {}
4821};
4822
4823/*
4824 */
4825#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4826#include "alc861_quirks.c"
4827#endif
4828
4829static int patch_alc861(struct hda_codec *codec)
4830{
4831 struct alc_spec *spec;
4832 int board_config;
4833 int err;
4834
4835 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4836 if (spec == NULL)
4837 return -ENOMEM;
4838
4839 codec->spec = spec;
4840
4841 spec->mixer_nid = 0x15;
4842
4843 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
4844 alc861_models, alc861_cfg_tbl);
4845
4846 if (board_config < 0) {
4847 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4848 codec->chip_name);
4849 board_config = ALC_MODEL_AUTO;
4850 }
4851
4852 if (board_config == ALC_MODEL_AUTO) {
4853 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
4854 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4855 }
4856
4857 if (board_config == ALC_MODEL_AUTO) {
4858 /* automatic parse from the BIOS config */
4859 err = alc861_parse_auto_config(codec);
4860 if (err < 0) {
4861 alc_free(codec);
4862 return err;
4863 }
4864#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4865 else if (!err) {
4866 printk(KERN_INFO
4867 "hda_codec: Cannot set up configuration "
4868 "from BIOS. Using base mode...\n");
4869 board_config = ALC861_3ST_DIG;
4870 }
4871#endif
4872 }
4873
Takashi Iwai1d045db2011-07-07 18:23:21 +02004874 if (board_config != ALC_MODEL_AUTO)
4875 setup_preset(codec, &alc861_presets[board_config]);
4876
Takashi Iwai60a6a842011-07-27 14:01:24 +02004877 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004878 alc_auto_fill_adc_caps(codec);
4879 alc_rebuild_imux_for_auto_mic(codec);
4880 alc_remove_invalid_adc_nids(codec);
4881 }
4882
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004883 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004884 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004885
4886 if (!spec->no_analog) {
4887 err = snd_hda_attach_beep_device(codec, 0x23);
4888 if (err < 0) {
4889 alc_free(codec);
4890 return err;
4891 }
4892 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
4893 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004894
4895 spec->vmaster_nid = 0x03;
4896
4897 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4898
4899 codec->patch_ops = alc_patch_ops;
4900 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02004901 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004902#ifdef CONFIG_SND_HDA_POWER_SAVE
4903 spec->power_hook = alc_power_eapd;
4904#endif
4905 }
4906#ifdef CONFIG_SND_HDA_POWER_SAVE
4907 if (!spec->loopback.amplist)
4908 spec->loopback.amplist = alc861_loopbacks;
4909#endif
4910
4911 return 0;
4912}
4913
4914/*
4915 * ALC861-VD support
4916 *
4917 * Based on ALC882
4918 *
4919 * In addition, an independent DAC
4920 */
4921#ifdef CONFIG_SND_HDA_POWER_SAVE
4922#define alc861vd_loopbacks alc880_loopbacks
4923#endif
4924
Takashi Iwai1d045db2011-07-07 18:23:21 +02004925static int alc861vd_parse_auto_config(struct hda_codec *codec)
4926{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004927 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004928 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4929 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004930}
4931
Takashi Iwai1d045db2011-07-07 18:23:21 +02004932enum {
4933 ALC660VD_FIX_ASUS_GPIO1
4934};
4935
4936/* reset GPIO1 */
4937static const struct alc_fixup alc861vd_fixups[] = {
4938 [ALC660VD_FIX_ASUS_GPIO1] = {
4939 .type = ALC_FIXUP_VERBS,
4940 .v.verbs = (const struct hda_verb[]) {
4941 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
4942 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4943 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4944 { }
4945 }
4946 },
4947};
4948
4949static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
4950 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
4951 {}
4952};
4953
4954static const struct hda_verb alc660vd_eapd_verbs[] = {
4955 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
4956 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
4957 { }
4958};
4959
4960/*
4961 */
4962#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4963#include "alc861vd_quirks.c"
4964#endif
4965
4966static int patch_alc861vd(struct hda_codec *codec)
4967{
4968 struct alc_spec *spec;
4969 int err, board_config;
4970
4971 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4972 if (spec == NULL)
4973 return -ENOMEM;
4974
4975 codec->spec = spec;
4976
4977 spec->mixer_nid = 0x0b;
4978
4979 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
4980 alc861vd_models, alc861vd_cfg_tbl);
4981
4982 if (board_config < 0) {
4983 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4984 codec->chip_name);
4985 board_config = ALC_MODEL_AUTO;
4986 }
4987
4988 if (board_config == ALC_MODEL_AUTO) {
4989 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
4990 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4991 }
4992
4993 if (board_config == ALC_MODEL_AUTO) {
4994 /* automatic parse from the BIOS config */
4995 err = alc861vd_parse_auto_config(codec);
4996 if (err < 0) {
4997 alc_free(codec);
4998 return err;
4999 }
5000#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5001 else if (!err) {
5002 printk(KERN_INFO
5003 "hda_codec: Cannot set up configuration "
5004 "from BIOS. Using base mode...\n");
5005 board_config = ALC861VD_3ST;
5006 }
5007#endif
5008 }
5009
Takashi Iwai1d045db2011-07-07 18:23:21 +02005010 if (board_config != ALC_MODEL_AUTO)
5011 setup_preset(codec, &alc861vd_presets[board_config]);
5012
5013 if (codec->vendor_id == 0x10ec0660) {
5014 /* always turn on EAPD */
5015 add_verb(spec, alc660vd_eapd_verbs);
5016 }
5017
Takashi Iwai60a6a842011-07-27 14:01:24 +02005018 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005019 alc_auto_fill_adc_caps(codec);
5020 alc_rebuild_imux_for_auto_mic(codec);
5021 alc_remove_invalid_adc_nids(codec);
5022 }
5023
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005024 if (!spec->no_analog && !spec->cap_mixer)
5025 set_capture_mixer(codec);
5026
5027 if (!spec->no_analog) {
5028 err = snd_hda_attach_beep_device(codec, 0x23);
5029 if (err < 0) {
5030 alc_free(codec);
5031 return err;
5032 }
5033 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5034 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005035
5036 spec->vmaster_nid = 0x02;
5037
5038 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5039
5040 codec->patch_ops = alc_patch_ops;
5041
5042 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005043 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005044 spec->shutup = alc_eapd_shutup;
5045#ifdef CONFIG_SND_HDA_POWER_SAVE
5046 if (!spec->loopback.amplist)
5047 spec->loopback.amplist = alc861vd_loopbacks;
5048#endif
5049
5050 return 0;
5051}
5052
5053/*
5054 * ALC662 support
5055 *
5056 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5057 * configuration. Each pin widget can choose any input DACs and a mixer.
5058 * Each ADC is connected from a mixer of all inputs. This makes possible
5059 * 6-channel independent captures.
5060 *
5061 * In addition, an independent DAC for the multi-playback (not used in this
5062 * driver yet).
5063 */
5064#ifdef CONFIG_SND_HDA_POWER_SAVE
5065#define alc662_loopbacks alc880_loopbacks
5066#endif
5067
5068/*
5069 * BIOS auto configuration
5070 */
5071
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005072static int alc662_parse_auto_config(struct hda_codec *codec)
5073{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005074 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005075 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5076 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5077 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005078
Kailang Yang6227cdc2010-02-25 08:36:52 +01005079 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5080 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005081 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005082 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005083 ssids = alc662_ssids;
5084 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005085}
5086
Todd Broch6be79482010-12-07 16:51:05 -08005087static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005088 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005089{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005090 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005091 return;
Todd Broch6be79482010-12-07 16:51:05 -08005092 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5093 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5094 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5095 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5096 (0 << AC_AMPCAP_MUTE_SHIFT)))
5097 printk(KERN_WARNING
5098 "hda_codec: failed to override amp caps for NID 0x2\n");
5099}
5100
David Henningsson6cb3b702010-09-09 08:51:44 +02005101enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005102 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005103 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005104 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005105 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005106 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005107 ALC662_FIXUP_HP_RP5800,
David Henningsson6cb3b702010-09-09 08:51:44 +02005108};
5109
5110static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005111 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005112 .type = ALC_FIXUP_PINS,
5113 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005114 { 0x15, 0x99130112 }, /* subwoofer */
5115 { }
5116 }
5117 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005118 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005119 .type = ALC_FIXUP_PINS,
5120 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005121 { 0x17, 0x99130112 }, /* subwoofer */
5122 { }
5123 }
5124 },
Todd Broch6be79482010-12-07 16:51:05 -08005125 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005126 .type = ALC_FIXUP_FUNC,
5127 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005128 },
5129 [ALC662_FIXUP_CZC_P10T] = {
5130 .type = ALC_FIXUP_VERBS,
5131 .v.verbs = (const struct hda_verb[]) {
5132 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5133 {}
5134 }
5135 },
David Henningsson94024cd2011-04-29 14:10:55 +02005136 [ALC662_FIXUP_SKU_IGNORE] = {
5137 .type = ALC_FIXUP_SKU,
5138 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005139 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005140 [ALC662_FIXUP_HP_RP5800] = {
5141 .type = ALC_FIXUP_PINS,
5142 .v.pins = (const struct alc_pincfg[]) {
5143 { 0x14, 0x0221201f }, /* HP out */
5144 { }
5145 },
5146 .chained = true,
5147 .chain_id = ALC662_FIXUP_SKU_IGNORE
5148 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005149};
5150
Takashi Iwaia9111322011-05-02 11:30:18 +02005151static const struct snd_pci_quirk alc662_fixup_tbl[] = {
David Henningssona6c47a82011-02-10 15:39:19 +01005152 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005153 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005154 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005155 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005156 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005157 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005158 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005159 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02005160 {}
5161};
5162
Todd Broch6be79482010-12-07 16:51:05 -08005163static const struct alc_model_fixup alc662_fixup_models[] = {
5164 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
5165 {}
5166};
David Henningsson6cb3b702010-09-09 08:51:44 +02005167
5168
Takashi Iwai1d045db2011-07-07 18:23:21 +02005169/*
5170 */
5171#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5172#include "alc662_quirks.c"
5173#endif
5174
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005175static int patch_alc662(struct hda_codec *codec)
5176{
5177 struct alc_spec *spec;
5178 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02005179 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005180
5181 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5182 if (!spec)
5183 return -ENOMEM;
5184
5185 codec->spec = spec;
5186
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005187 spec->mixer_nid = 0x0b;
5188
Kailang Yangda00c242010-03-19 11:23:45 +01005189 alc_auto_parse_customize_define(codec);
5190
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005191 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5192
Kailang Yang693194f2010-10-21 08:51:48 +02005193 coef = alc_read_coef_idx(codec, 0);
5194 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005195 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005196 else if (coef & (1 << 14) &&
5197 codec->bus->pci->subsystem_vendor == 0x1025 &&
5198 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005199 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005200 else if (coef == 0x4011)
5201 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005202
Takashi Iwai1d045db2011-07-07 18:23:21 +02005203 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
5204 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005205 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005206 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5207 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005208 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005209 }
5210
Takashi Iwai1d045db2011-07-07 18:23:21 +02005211 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005212 alc_pick_fixup(codec, alc662_fixup_models,
5213 alc662_fixup_tbl, alc662_fixups);
5214 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005215 /* automatic parse from the BIOS config */
5216 err = alc662_parse_auto_config(codec);
5217 if (err < 0) {
5218 alc_free(codec);
5219 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005220 }
5221#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5222 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005223 printk(KERN_INFO
5224 "hda_codec: Cannot set up configuration "
5225 "from BIOS. Using base mode...\n");
5226 board_config = ALC662_3ST_2ch_DIG;
5227 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005228#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005229 }
5230
Takashi Iwai1d045db2011-07-07 18:23:21 +02005231 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005232 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005233
Takashi Iwai60a6a842011-07-27 14:01:24 +02005234 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005235 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005236 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005237 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005238 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005239
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005240 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005241 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005242
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005243 if (!spec->no_analog && has_cdefine_beep(codec)) {
5244 err = snd_hda_attach_beep_device(codec, 0x1);
5245 if (err < 0) {
5246 alc_free(codec);
5247 return err;
5248 }
Kailang Yangda00c242010-03-19 11:23:45 +01005249 switch (codec->vendor_id) {
5250 case 0x10ec0662:
5251 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5252 break;
5253 case 0x10ec0272:
5254 case 0x10ec0663:
5255 case 0x10ec0665:
5256 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5257 break;
5258 case 0x10ec0273:
5259 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5260 break;
5261 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005262 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005263 spec->vmaster_nid = 0x02;
5264
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005265 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5266
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005267 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005268 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005269 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c716152011-04-07 10:37:16 +02005270 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005271
Kailang Yangbf1b0222010-10-21 08:49:56 +02005272 alc_init_jacks(codec);
5273
Takashi Iwaicb53c622007-08-10 17:21:45 +02005274#ifdef CONFIG_SND_HDA_POWER_SAVE
5275 if (!spec->loopback.amplist)
5276 spec->loopback.amplist = alc662_loopbacks;
5277#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005278
5279 return 0;
5280}
5281
Kailang Yang274693f2009-12-03 10:07:50 +01005282static int patch_alc888(struct hda_codec *codec)
5283{
5284 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5285 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005286 if (codec->vendor_id == 0x10ec0887)
5287 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5288 else
5289 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005290 if (!codec->chip_name) {
5291 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005292 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005293 }
5294 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005295 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005296 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005297}
5298
Kailang Yangb478b992011-05-18 11:51:15 +02005299static int patch_alc899(struct hda_codec *codec)
5300{
5301 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5302 kfree(codec->chip_name);
5303 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5304 }
5305 return patch_alc882(codec);
5306}
5307
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005308/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005309 * ALC680 support
5310 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005311
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005312static int alc680_parse_auto_config(struct hda_codec *codec)
5313{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005314 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005315}
5316
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005317/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005318 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005319#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5320#include "alc680_quirks.c"
5321#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005322
5323static int patch_alc680(struct hda_codec *codec)
5324{
5325 struct alc_spec *spec;
5326 int board_config;
5327 int err;
5328
5329 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5330 if (spec == NULL)
5331 return -ENOMEM;
5332
5333 codec->spec = spec;
5334
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005335 /* ALC680 has no aa-loopback mixer */
5336
Takashi Iwai1d045db2011-07-07 18:23:21 +02005337 board_config = alc_board_config(codec, ALC680_MODEL_LAST,
5338 alc680_models, alc680_cfg_tbl);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005339
Takashi Iwai1d045db2011-07-07 18:23:21 +02005340 if (board_config < 0) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005341 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5342 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005343 board_config = ALC_MODEL_AUTO;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005344 }
5345
Takashi Iwai1d045db2011-07-07 18:23:21 +02005346 if (board_config == ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005347 /* automatic parse from the BIOS config */
5348 err = alc680_parse_auto_config(codec);
5349 if (err < 0) {
5350 alc_free(codec);
5351 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005352 }
5353#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5354 else if (!err) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005355 printk(KERN_INFO
5356 "hda_codec: Cannot set up configuration "
5357 "from BIOS. Using base mode...\n");
5358 board_config = ALC680_BASE;
5359 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005360#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005361 }
5362
Takashi Iwai1d045db2011-07-07 18:23:21 +02005363 if (board_config != ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005364 setup_preset(codec, &alc680_presets[board_config]);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005365#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
Takashi Iwai21268962011-07-07 15:01:13 +02005366 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005367#endif
Takashi Iwai21268962011-07-07 15:01:13 +02005368 }
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005369
Takashi Iwai60a6a842011-07-27 14:01:24 +02005370 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005371 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005372 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005373 alc_remove_invalid_adc_nids(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005374 }
5375
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005376 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005377 set_capture_mixer(codec);
5378
5379 spec->vmaster_nid = 0x02;
5380
5381 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005382 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005383 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005384
5385 return 0;
5386}
5387
5388/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389 * patch entries
5390 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005391static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005392 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005393 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005394 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005395 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005396 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005397 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005398 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005399 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005400 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005401 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005402 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005403 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005404 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5405 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5406 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005407 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +02005408 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005409 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5410 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005411 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005412 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005413 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005414 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005415 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +02005417 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005418 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005419 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005420 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005421 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005422 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005423 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005424 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +02005425 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005426 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai49535502009-06-30 15:28:30 +02005427 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005428 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005429 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430 {} /* terminator */
5431};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005432
5433MODULE_ALIAS("snd-hda-codec-id:10ec*");
5434
5435MODULE_LICENSE("GPL");
5436MODULE_DESCRIPTION("Realtek HD-audio codec");
5437
5438static struct hda_codec_preset_list realtek_list = {
5439 .preset = snd_hda_preset_realtek,
5440 .owner = THIS_MODULE,
5441};
5442
5443static int __init patch_realtek_init(void)
5444{
5445 return snd_hda_add_codec_preset(&realtek_list);
5446}
5447
5448static void __exit patch_realtek_exit(void)
5449{
5450 snd_hda_delete_codec_preset(&realtek_list);
5451}
5452
5453module_init(patch_realtek_init)
5454module_exit(patch_realtek_exit)