blob: 91a538173c977e75fcabcdb8767b24d8dd6207a9 [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 Woithe7cf51e482006-02-09 12:01:26 +01009 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020031#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "hda_codec.h"
33#include "hda_local.h"
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090034#include "hda_beep.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Takashi Iwai1d045db2011-07-07 18:23:21 +020036/* unsol event tags */
37#define ALC_FRONT_EVENT 0x01
38#define ALC_DCVOL_EVENT 0x02
39#define ALC_HP_EVENT 0x04
40#define ALC_MIC_EVENT 0x08
Takashi Iwaid4a86d82010-06-23 17:51:26 +020041
Kailang Yangdf694da2005-12-05 19:42:22 +010042/* for GPIO Poll */
43#define GPIO_MASK 0x03
44
Takashi Iwai4a79ba32009-04-22 16:31:35 +020045/* extra amp-initialization sequence types */
46enum {
47 ALC_INIT_NONE,
48 ALC_INIT_DEFAULT,
49 ALC_INIT_GPIO1,
50 ALC_INIT_GPIO2,
51 ALC_INIT_GPIO3,
52};
53
Kailang Yangda00c242010-03-19 11:23:45 +010054struct alc_customize_define {
55 unsigned int sku_cfg;
56 unsigned char port_connectivity;
57 unsigned char check_sum;
58 unsigned char customization;
59 unsigned char external_amp;
60 unsigned int enable_pcbeep:1;
61 unsigned int platform_type:1;
62 unsigned int swap:1;
63 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020064 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010065};
66
Takashi Iwaib5bfbc62011-01-13 14:22:32 +010067struct alc_fixup;
68
Takashi Iwaice764ab2011-04-27 16:35:23 +020069struct alc_multi_io {
70 hda_nid_t pin; /* multi-io widget pin NID */
71 hda_nid_t dac; /* DAC to be connected */
72 unsigned int ctl_in; /* cached input-pin control value */
73};
74
Takashi Iwaid922b512011-04-28 12:18:53 +020075enum {
Takashi Iwai3b8510c2011-04-28 14:03:24 +020076 ALC_AUTOMUTE_PIN, /* change the pin control */
77 ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
78 ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
Takashi Iwaid922b512011-04-28 12:18:53 +020079};
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081struct alc_spec {
82 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020083 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 unsigned int num_mixers;
Takashi Iwaia9111322011-05-02 11:30:18 +020085 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010086 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwai2d9c6482009-10-13 08:06:55 +020088 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +020089 * don't forget NULL
90 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +020091 */
92 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Takashi Iwaiaa563af2009-07-31 10:05:11 +020094 char stream_name_analog[32]; /* analog PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +020095 const struct hda_pcm_stream *stream_analog_playback;
96 const struct hda_pcm_stream *stream_analog_capture;
97 const struct hda_pcm_stream *stream_analog_alt_playback;
98 const struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200100 char stream_name_digital[32]; /* digital PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +0200101 const struct hda_pcm_stream *stream_digital_playback;
102 const struct hda_pcm_stream *stream_digital_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200105 struct hda_multi_out multiout; /* playback set-up
106 * max_channels, dacs must be set
107 * dig_out_nid and hp_nid are optional
108 */
Takashi Iwai63300792008-01-24 15:31:36 +0100109 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100110 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100111 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 /* capture */
114 unsigned int num_adc_nids;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +0200115 const hda_nid_t *adc_nids;
116 const hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200117 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Takashi Iwai1f0f4b82011-06-27 10:52:59 +0200118 hda_nid_t mixer_nid; /* analog-mixer NID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Takashi Iwai840b64c2010-07-13 22:49:01 +0200120 /* capture setup for dynamic dual-adc switch */
Takashi Iwai840b64c2010-07-13 22:49:01 +0200121 hda_nid_t cur_adc;
122 unsigned int cur_adc_stream_tag;
123 unsigned int cur_adc_format;
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200126 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 const struct hda_input_mux *input_mux;
128 unsigned int cur_mux[3];
Takashi Iwai21268962011-07-07 15:01:13 +0200129 hda_nid_t ext_mic_pin;
130 hda_nid_t dock_mic_pin;
131 hda_nid_t int_mic_pin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100134 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200136 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200137 int const_channel_count;
138 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100141 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200142
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200143 /* dynamic controls, init_verbs and input_mux */
144 struct auto_pin_cfg autocfg;
Kailang Yangda00c242010-03-19 11:23:45 +0100145 struct alc_customize_define cdefine;
Takashi Iwai603c4012008-07-30 15:01:44 +0200146 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200147 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200148 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai4953550a2009-06-30 15:28:30 +0200149 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
150 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai21268962011-07-07 15:01:13 +0200151 hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
152 unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
153 int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
Takashi Iwai834be882006-03-01 14:16:17 +0100154
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100155 /* hooks */
156 void (*init_hook)(struct hda_codec *codec);
157 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100158#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500159 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100160#endif
Takashi Iwai1c7161532011-04-07 10:37:16 +0200161 void (*shutup)(struct hda_codec *codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100162
Takashi Iwai834be882006-03-01 14:16:17 +0100163 /* for pin sensing */
Takashi Iwai834be882006-03-01 14:16:17 +0100164 unsigned int jack_present: 1;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200165 unsigned int line_jack_present:1;
Takashi Iwaie9427962011-04-28 15:46:07 +0200166 unsigned int master_mute:1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200167 unsigned int auto_mic:1;
Takashi Iwai21268962011-07-07 15:01:13 +0200168 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
Takashi Iwaid922b512011-04-28 12:18:53 +0200169 unsigned int automute:1; /* HP automute enabled */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200170 unsigned int detect_line:1; /* Line-out detection enabled */
Takashi Iwai8974bd512011-09-19 11:31:34 +0200171 unsigned int automute_lines:1; /* automute line-out as well; NOP when automute_hp_lo isn't set */
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200172 unsigned int automute_hp_lo:1; /* both HP and LO available */
Takashi Iwaicb53c622007-08-10 17:21:45 +0200173
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100174 /* other flags */
175 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai21268962011-07-07 15:01:13 +0200176 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai584c0c42011-03-10 12:51:11 +0100177 unsigned int single_input_src:1;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +0200178 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
Takashi Iwaid922b512011-04-28 12:18:53 +0200179
180 /* auto-mute control */
181 int automute_mode;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200182 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
Takashi Iwaid922b512011-04-28 12:18:53 +0200183
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200184 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200185 int codec_variant; /* flag for other variants */
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100186
Takashi Iwai2134ea42008-01-10 16:53:55 +0100187 /* for virtual master */
188 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200189#ifdef CONFIG_SND_HDA_POWER_SAVE
190 struct hda_loopback_check loopback;
191#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200192
193 /* for PLL fix */
194 hda_nid_t pll_nid;
195 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +0100196
197 /* fix-up list */
198 int fixup_id;
199 const struct alc_fixup *fixup_list;
200 const char *fixup_name;
Takashi Iwaice764ab2011-04-27 16:35:23 +0200201
202 /* multi-io */
203 int multi_ios;
204 struct alc_multi_io multi_io[4];
Kailang Yangdf694da2005-12-05 19:42:22 +0100205};
206
Takashi Iwai1d045db2011-07-07 18:23:21 +0200207#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Takashi Iwai44c02402011-07-08 15:14:19 +0200209static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
210 int dir, unsigned int bits)
211{
212 if (!nid)
213 return false;
214 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
215 if (query_amp_caps(codec, nid, dir) & bits)
216 return true;
217 return false;
218}
219
220#define nid_has_mute(codec, nid, dir) \
221 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
222#define nid_has_volume(codec, nid, dir) \
223 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225/*
226 * input MUX handling
227 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200228static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
229 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230{
231 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
232 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200233 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
234 if (mux_idx >= spec->num_mux_defs)
235 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100236 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
237 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200238 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200241static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
244 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
245 struct alc_spec *spec = codec->spec;
246 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
247
248 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
249 return 0;
250}
251
Takashi Iwai21268962011-07-07 15:01:13 +0200252static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253{
Takashi Iwai21268962011-07-07 15:01:13 +0200254 struct alc_spec *spec = codec->spec;
255 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
256
257 if (spec->cur_adc && spec->cur_adc != new_adc) {
258 /* stream is running, let's swap the current ADC */
259 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
260 spec->cur_adc = new_adc;
261 snd_hda_codec_setup_stream(codec, new_adc,
262 spec->cur_adc_stream_tag, 0,
263 spec->cur_adc_format);
264 return true;
265 }
266 return false;
267}
268
269/* select the given imux item; either unmute exclusively or select the route */
270static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
271 unsigned int idx, bool force)
272{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100274 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100275 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200276 int i, type;
277 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Takashi Iwaicd896c32008-11-18 12:36:33 +0100279 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
280 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100281 if (!imux->num_items && mux_idx > 0)
282 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100283
Takashi Iwai21268962011-07-07 15:01:13 +0200284 if (idx >= imux->num_items)
285 idx = imux->num_items - 1;
286 if (spec->cur_mux[adc_idx] == idx && !force)
287 return 0;
288 spec->cur_mux[adc_idx] = idx;
289
290 if (spec->dyn_adc_switch) {
291 alc_dyn_adc_pcm_resetup(codec, idx);
292 adc_idx = spec->dyn_adc_idx[idx];
293 }
294
295 nid = spec->capsrc_nids ?
296 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
297
298 /* no selection? */
299 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
300 return 1;
301
Takashi Iwaia22d5432009-07-27 12:54:26 +0200302 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200303 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100304 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100305 for (i = 0; i < imux->num_items; i++) {
306 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
307 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
308 imux->items[i].index,
309 HDA_AMP_MUTE, v);
310 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100311 } else {
312 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200313 snd_hda_codec_write_cache(codec, nid, 0,
314 AC_VERB_SET_CONNECT_SEL,
315 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100316 }
Takashi Iwai21268962011-07-07 15:01:13 +0200317 return 1;
318}
319
320static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
321 struct snd_ctl_elem_value *ucontrol)
322{
323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
324 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
325 return alc_mux_select(codec, adc_idx,
326 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100327}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100330 * set up the input pin config (depending on the given auto-pin type)
331 */
332static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
333 int auto_pin_type)
334{
335 unsigned int val = PIN_IN;
336
Takashi Iwai86e29592010-09-09 14:50:17 +0200337 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100338 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200339 unsigned int oldval;
340 oldval = snd_hda_codec_read(codec, nid, 0,
341 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100342 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100343 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200344 /* if the default pin setup is vref50, we give it priority */
345 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100346 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200347 else if (pincap & AC_PINCAP_VREF_50)
348 val = PIN_VREF50;
349 else if (pincap & AC_PINCAP_VREF_100)
350 val = PIN_VREF100;
351 else if (pincap & AC_PINCAP_VREF_GRD)
352 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100353 }
354 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
355}
356
357/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200358 * Append the given mixer and verb elements for the later use
359 * The mixer array is referred in build_controls(), and init_verbs are
360 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100361 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200362static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100363{
364 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
365 return;
366 spec->mixers[spec->num_mixers++] = mix;
367}
368
369static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
370{
371 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
372 return;
373 spec->init_verbs[spec->num_init_verbs++] = verb;
374}
375
376/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200377 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100378 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200379/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200380static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200381 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
382 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
383 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
384 { }
385};
386
Takashi Iwaia9111322011-05-02 11:30:18 +0200387static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200388 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
389 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
390 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
391 { }
392};
393
Takashi Iwaia9111322011-05-02 11:30:18 +0200394static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200395 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
396 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
397 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
398 { }
399};
400
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200401/*
402 * Fix hardware PLL issue
403 * On some codecs, the analog PLL gating control must be off while
404 * the default value is 1.
405 */
406static void alc_fix_pll(struct hda_codec *codec)
407{
408 struct alc_spec *spec = codec->spec;
409 unsigned int val;
410
411 if (!spec->pll_nid)
412 return;
413 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
414 spec->pll_coef_idx);
415 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
416 AC_VERB_GET_PROC_COEF, 0);
417 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
418 spec->pll_coef_idx);
419 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
420 val & ~(1 << spec->pll_coef_bit));
421}
422
423static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
424 unsigned int coef_idx, unsigned int coef_bit)
425{
426 struct alc_spec *spec = codec->spec;
427 spec->pll_nid = nid;
428 spec->pll_coef_idx = coef_idx;
429 spec->pll_coef_bit = coef_bit;
430 alc_fix_pll(codec);
431}
432
Takashi Iwai1d045db2011-07-07 18:23:21 +0200433/*
434 * Jack-reporting via input-jack layer
435 */
436
437/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200438static int alc_init_jacks(struct hda_codec *codec)
439{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100440#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200441 struct alc_spec *spec = codec->spec;
442 int err;
443 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200444 unsigned int mic_nid = spec->ext_mic_pin;
445 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200446
Takashi Iwai265a0242010-09-21 11:26:21 +0200447 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100448 err = snd_hda_input_jack_add(codec, hp_nid,
449 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200450 if (err < 0)
451 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100452 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200453 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200454
Takashi Iwai265a0242010-09-21 11:26:21 +0200455 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100456 err = snd_hda_input_jack_add(codec, mic_nid,
457 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200458 if (err < 0)
459 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100460 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200461 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200462 if (dock_nid) {
463 err = snd_hda_input_jack_add(codec, dock_nid,
464 SND_JACK_MICROPHONE, NULL);
465 if (err < 0)
466 return err;
467 snd_hda_input_jack_report(codec, dock_nid);
468 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100469#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200470 return 0;
471}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200472
Takashi Iwai1d045db2011-07-07 18:23:21 +0200473/*
474 * Jack detections for HP auto-mute and mic-switch
475 */
476
477/* check each pin in the given array; returns true if any of them is plugged */
478static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200479{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200480 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200481
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200482 for (i = 0; i < num_pins; i++) {
483 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200484 if (!nid)
485 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100486 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200487 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200488 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200489 return present;
490}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200491
Takashi Iwai1d045db2011-07-07 18:23:21 +0200492/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200493static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200494 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200495{
496 struct alc_spec *spec = codec->spec;
497 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200498 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200499 int i;
500
501 for (i = 0; i < num_pins; i++) {
502 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200503 if (!nid)
504 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200505 switch (spec->automute_mode) {
506 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200507 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200508 AC_VERB_SET_PIN_WIDGET_CONTROL,
509 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200510 break;
511 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200512 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200513 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200514 break;
515 case ALC_AUTOMUTE_MIXER:
516 nid = spec->automute_mixer_nid[i];
517 if (!nid)
518 break;
519 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200520 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200521 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200522 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200523 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200524 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200525 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200526}
527
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200528/* Toggle internal speakers muting */
529static void update_speakers(struct hda_codec *codec)
530{
531 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200532 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200533
Takashi Iwaic0a20262011-06-10 15:28:15 +0200534 /* Control HP pins/amps depending on master_mute state;
535 * in general, HP pins/amps control should be enabled in all cases,
536 * but currently set only for master_mute, just to be safe
537 */
538 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
539 spec->autocfg.hp_pins, spec->master_mute, true);
540
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200541 if (!spec->automute)
542 on = 0;
543 else
544 on = spec->jack_present | spec->line_jack_present;
545 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200546 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200547 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200548
549 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200550 /* if LO is a copy of either HP or Speaker, don't need to handle it */
551 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
552 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200553 return;
Takashi Iwai8974bd512011-09-19 11:31:34 +0200554 if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200555 on = 0;
556 else
557 on = spec->jack_present;
558 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200559 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200560 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200561}
562
Takashi Iwai1d045db2011-07-07 18:23:21 +0200563/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200564static void alc_hp_automute(struct hda_codec *codec)
565{
566 struct alc_spec *spec = codec->spec;
567
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200568 spec->jack_present =
569 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
570 spec->autocfg.hp_pins);
Takashi Iwai3c715a92011-08-23 12:41:09 +0200571 if (!spec->automute)
572 return;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200573 update_speakers(codec);
574}
575
Takashi Iwai1d045db2011-07-07 18:23:21 +0200576/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200577static void alc_line_automute(struct hda_codec *codec)
578{
579 struct alc_spec *spec = codec->spec;
580
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200581 spec->line_jack_present =
582 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
583 spec->autocfg.line_out_pins);
Takashi Iwai3c715a92011-08-23 12:41:09 +0200584 if (!spec->automute || !spec->detect_line)
585 return;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200586 update_speakers(codec);
587}
588
Takashi Iwai8d087c72011-06-28 12:45:47 +0200589#define get_connection_index(codec, mux, nid) \
590 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200591
Takashi Iwai1d045db2011-07-07 18:23:21 +0200592/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200593static void alc_mic_automute(struct hda_codec *codec)
594{
595 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200596 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200597
Takashi Iwai21268962011-07-07 15:01:13 +0200598 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200599 return;
600 if (snd_BUG_ON(!spec->adc_nids))
601 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200602 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200603 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200604
Takashi Iwai21268962011-07-07 15:01:13 +0200605 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
606 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
607 else if (spec->dock_mic_idx >= 0 &&
608 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
609 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
610 else
611 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200612
Takashi Iwai21268962011-07-07 15:01:13 +0200613 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
614 if (spec->dock_mic_idx >= 0)
615 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200616}
617
Kailang Yangc9b58002007-10-16 14:30:01 +0200618/* unsolicited event for HP jack sensing */
619static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
620{
621 if (codec->vendor_id == 0x10ec0880)
622 res >>= 28;
623 else
624 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200625 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200626 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200627 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200628 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200629 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200630 alc_line_automute(codec);
631 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200632 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200633 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200634 break;
635 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200636}
637
Takashi Iwai1d045db2011-07-07 18:23:21 +0200638/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200639static void alc_inithook(struct hda_codec *codec)
640{
Takashi Iwaid922b512011-04-28 12:18:53 +0200641 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200642 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200643 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200644}
645
Kailang Yangf9423e72008-05-27 12:32:25 +0200646/* additional initialization for ALC888 variants */
647static void alc888_coef_init(struct hda_codec *codec)
648{
649 unsigned int tmp;
650
651 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
652 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
653 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100654 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200655 /* alc888S-VC */
656 snd_hda_codec_read(codec, 0x20, 0,
657 AC_VERB_SET_PROC_COEF, 0x830);
658 else
659 /* alc888-VB */
660 snd_hda_codec_read(codec, 0x20, 0,
661 AC_VERB_SET_PROC_COEF, 0x3030);
662}
663
Takashi Iwai1d045db2011-07-07 18:23:21 +0200664/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200665static void alc889_coef_init(struct hda_codec *codec)
666{
667 unsigned int tmp;
668
669 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
670 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
671 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
672 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
673}
674
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100675/* turn on/off EAPD control (only if available) */
676static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
677{
678 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
679 return;
680 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
681 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
682 on ? 2 : 0);
683}
684
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200685/* turn on/off EAPD controls of the codec */
686static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
687{
688 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200689 static hda_nid_t pins[] = {
690 0x0f, 0x10, 0x14, 0x15, 0
691 };
692 hda_nid_t *p;
693 for (p = pins; *p; p++)
694 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200695}
696
Takashi Iwai1c7161532011-04-07 10:37:16 +0200697/* generic shutup callback;
698 * just turning off EPAD and a little pause for avoiding pop-noise
699 */
700static void alc_eapd_shutup(struct hda_codec *codec)
701{
702 alc_auto_setup_eapd(codec, false);
703 msleep(200);
704}
705
Takashi Iwai1d045db2011-07-07 18:23:21 +0200706/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200707static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200708{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200709 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200710
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200711 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200712 switch (type) {
713 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200714 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
715 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200716 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200717 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
718 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200719 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200720 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
721 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200722 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200723 switch (codec->vendor_id) {
724 case 0x10ec0260:
725 snd_hda_codec_write(codec, 0x1a, 0,
726 AC_VERB_SET_COEF_INDEX, 7);
727 tmp = snd_hda_codec_read(codec, 0x1a, 0,
728 AC_VERB_GET_PROC_COEF, 0);
729 snd_hda_codec_write(codec, 0x1a, 0,
730 AC_VERB_SET_COEF_INDEX, 7);
731 snd_hda_codec_write(codec, 0x1a, 0,
732 AC_VERB_SET_PROC_COEF,
733 tmp | 0x2010);
734 break;
735 case 0x10ec0262:
736 case 0x10ec0880:
737 case 0x10ec0882:
738 case 0x10ec0883:
739 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100740 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100741 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200742 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200743 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200744 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200745 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200746 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100747#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200748 case 0x10ec0267:
749 case 0x10ec0268:
750 snd_hda_codec_write(codec, 0x20, 0,
751 AC_VERB_SET_COEF_INDEX, 7);
752 tmp = snd_hda_codec_read(codec, 0x20, 0,
753 AC_VERB_GET_PROC_COEF, 0);
754 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200755 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200756 snd_hda_codec_write(codec, 0x20, 0,
757 AC_VERB_SET_PROC_COEF,
758 tmp | 0x3000);
759 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100760#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200761 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200762 break;
763 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200764}
Kailang Yangea1fb292008-08-26 12:58:38 +0200765
Takashi Iwai1d045db2011-07-07 18:23:21 +0200766/*
767 * Auto-Mute mode mixer enum support
768 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200769static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
770 struct snd_ctl_elem_info *uinfo)
771{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200772 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
773 struct alc_spec *spec = codec->spec;
774 static const char * const texts2[] = {
775 "Disabled", "Enabled"
776 };
777 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200778 "Disabled", "Speaker Only", "Line-Out+Speaker"
779 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200780 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200781
782 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
783 uinfo->count = 1;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200784 if (spec->automute_hp_lo) {
785 uinfo->value.enumerated.items = 3;
786 texts = texts3;
787 } else {
788 uinfo->value.enumerated.items = 2;
789 texts = texts2;
790 }
791 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
792 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200793 strcpy(uinfo->value.enumerated.name,
794 texts[uinfo->value.enumerated.item]);
795 return 0;
796}
797
798static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
799 struct snd_ctl_elem_value *ucontrol)
800{
801 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
802 struct alc_spec *spec = codec->spec;
803 unsigned int val;
804 if (!spec->automute)
805 val = 0;
Takashi Iwai8974bd512011-09-19 11:31:34 +0200806 else if (!spec->automute_hp_lo || !spec->automute_lines)
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200807 val = 1;
808 else
809 val = 2;
810 ucontrol->value.enumerated.item[0] = val;
811 return 0;
812}
813
814static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
815 struct snd_ctl_elem_value *ucontrol)
816{
817 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
818 struct alc_spec *spec = codec->spec;
819
820 switch (ucontrol->value.enumerated.item[0]) {
821 case 0:
822 if (!spec->automute)
823 return 0;
824 spec->automute = 0;
825 break;
826 case 1:
Takashi Iwai8974bd512011-09-19 11:31:34 +0200827 if (spec->automute &&
828 (!spec->automute_hp_lo || !spec->automute_lines))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200829 return 0;
830 spec->automute = 1;
831 spec->automute_lines = 0;
832 break;
833 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200834 if (!spec->automute_hp_lo)
835 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200836 if (spec->automute && spec->automute_lines)
837 return 0;
838 spec->automute = 1;
839 spec->automute_lines = 1;
840 break;
841 default:
842 return -EINVAL;
843 }
844 update_speakers(codec);
845 return 1;
846}
847
Takashi Iwaia9111322011-05-02 11:30:18 +0200848static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200849 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
850 .name = "Auto-Mute Mode",
851 .info = alc_automute_mode_info,
852 .get = alc_automute_mode_get,
853 .put = alc_automute_mode_put,
854};
855
Takashi Iwai1d045db2011-07-07 18:23:21 +0200856static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
857{
858 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
859 return snd_array_new(&spec->kctls);
860}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200861
862static int alc_add_automute_mode_enum(struct hda_codec *codec)
863{
864 struct alc_spec *spec = codec->spec;
865 struct snd_kcontrol_new *knew;
866
867 knew = alc_kcontrol_new(spec);
868 if (!knew)
869 return -ENOMEM;
870 *knew = alc_automute_mode_enum;
871 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
872 if (!knew->name)
873 return -ENOMEM;
874 return 0;
875}
876
Takashi Iwai1d045db2011-07-07 18:23:21 +0200877/*
878 * Check the availability of HP/line-out auto-mute;
879 * Set up appropriately if really supported
880 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200881static void alc_init_auto_hp(struct hda_codec *codec)
882{
883 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200884 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200885 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200886 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200887
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200888 if (cfg->hp_pins[0])
889 present++;
890 if (cfg->line_out_pins[0])
891 present++;
892 if (cfg->speaker_pins[0])
893 present++;
894 if (present < 2) /* need two different output types */
895 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200896 if (present == 3)
897 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200898
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200899 if (!cfg->speaker_pins[0] &&
900 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200901 memcpy(cfg->speaker_pins, cfg->line_out_pins,
902 sizeof(cfg->speaker_pins));
903 cfg->speaker_outs = cfg->line_outs;
904 }
905
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200906 if (!cfg->hp_pins[0] &&
907 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200908 memcpy(cfg->hp_pins, cfg->line_out_pins,
909 sizeof(cfg->hp_pins));
910 cfg->hp_outs = cfg->line_outs;
911 }
912
913 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200914 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200915 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200916 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200917 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200918 nid);
919 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200920 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200921 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200922 spec->automute = 1;
923 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200924 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200925 if (spec->automute && cfg->line_out_pins[0] &&
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200926 cfg->speaker_pins[0] &&
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200927 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
928 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
929 for (i = 0; i < cfg->line_outs; i++) {
930 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200931 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200932 continue;
933 snd_printdd("realtek: Enable Line-Out auto-muting "
934 "on NID 0x%x\n", nid);
935 snd_hda_codec_write_cache(codec, nid, 0,
936 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200937 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200938 spec->detect_line = 1;
939 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200940 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200941 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200942
943 if (spec->automute) {
944 /* create a control for automute mode */
945 alc_add_automute_mode_enum(codec);
946 spec->unsol_event = alc_sku_unsol_event;
947 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200948}
949
Takashi Iwai1d045db2011-07-07 18:23:21 +0200950/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200951static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
952{
953 int i;
954 for (i = 0; i < nums; i++)
955 if (list[i] == nid)
956 return i;
957 return -1;
958}
959
Takashi Iwai1d045db2011-07-07 18:23:21 +0200960/* check whether dynamic ADC-switching is available */
961static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
962{
963 struct alc_spec *spec = codec->spec;
964 struct hda_input_mux *imux = &spec->private_imux[0];
965 int i, n, idx;
966 hda_nid_t cap, pin;
967
968 if (imux != spec->input_mux) /* no dynamic imux? */
969 return false;
970
971 for (n = 0; n < spec->num_adc_nids; n++) {
972 cap = spec->private_capsrc_nids[n];
973 for (i = 0; i < imux->num_items; i++) {
974 pin = spec->imux_pins[i];
975 if (!pin)
976 return false;
977 if (get_connection_index(codec, cap, pin) < 0)
978 break;
979 }
980 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +0200981 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +0200982 }
983
984 for (i = 0; i < imux->num_items; i++) {
985 pin = spec->imux_pins[i];
986 for (n = 0; n < spec->num_adc_nids; n++) {
987 cap = spec->private_capsrc_nids[n];
988 idx = get_connection_index(codec, cap, pin);
989 if (idx >= 0) {
990 imux->items[i].index = idx;
991 spec->dyn_adc_idx[i] = n;
992 break;
993 }
994 }
995 }
996
997 snd_printdd("realtek: enabling ADC switching\n");
998 spec->dyn_adc_switch = 1;
999 return true;
1000}
Takashi Iwai21268962011-07-07 15:01:13 +02001001
1002/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1003static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1004{
1005 struct alc_spec *spec = codec->spec;
1006 struct hda_input_mux *imux;
1007 static char * const texts[3] = {
1008 "Mic", "Internal Mic", "Dock Mic"
1009 };
1010 int i;
1011
1012 if (!spec->auto_mic)
1013 return false;
1014 imux = &spec->private_imux[0];
1015 if (spec->input_mux == imux)
1016 return true;
1017 spec->imux_pins[0] = spec->ext_mic_pin;
1018 spec->imux_pins[1] = spec->int_mic_pin;
1019 spec->imux_pins[2] = spec->dock_mic_pin;
1020 for (i = 0; i < 3; i++) {
1021 strcpy(imux->items[i].label, texts[i]);
1022 if (spec->imux_pins[i])
1023 imux->num_items = i + 1;
1024 }
1025 spec->num_mux_defs = 1;
1026 spec->input_mux = imux;
1027 return true;
1028}
1029
1030/* check whether all auto-mic pins are valid; setup indices if OK */
1031static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1032{
1033 struct alc_spec *spec = codec->spec;
1034 const struct hda_input_mux *imux;
1035
1036 if (!spec->auto_mic)
1037 return false;
1038 if (spec->auto_mic_valid_imux)
1039 return true; /* already checked */
1040
1041 /* fill up imux indices */
1042 if (!alc_check_dyn_adc_switch(codec)) {
1043 spec->auto_mic = 0;
1044 return false;
1045 }
1046
1047 imux = spec->input_mux;
1048 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1049 spec->imux_pins, imux->num_items);
1050 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1051 spec->imux_pins, imux->num_items);
1052 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1053 spec->imux_pins, imux->num_items);
1054 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1055 spec->auto_mic = 0;
1056 return false; /* no corresponding imux */
1057 }
1058
1059 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1060 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001061 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001062 if (spec->dock_mic_pin)
1063 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1064 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001065 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001066
1067 spec->auto_mic_valid_imux = 1;
1068 spec->auto_mic = 1;
1069 return true;
1070}
1071
Takashi Iwai1d045db2011-07-07 18:23:21 +02001072/*
1073 * Check the availability of auto-mic switch;
1074 * Set up if really supported
1075 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001076static void alc_init_auto_mic(struct hda_codec *codec)
1077{
1078 struct alc_spec *spec = codec->spec;
1079 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001080 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001081 int i;
1082
Takashi Iwai21268962011-07-07 15:01:13 +02001083 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1084
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001085 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001086 for (i = 0; i < cfg->num_inputs; i++) {
1087 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001088 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001089 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001090 switch (snd_hda_get_input_pin_attr(defcfg)) {
1091 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001092 if (fixed)
1093 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001094 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1095 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001096 fixed = nid;
1097 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001098 case INPUT_PIN_ATTR_UNUSED:
1099 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001100 case INPUT_PIN_ATTR_DOCK:
1101 if (dock)
1102 return; /* already occupied */
1103 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1104 return; /* invalid type */
1105 dock = nid;
1106 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001107 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001108 if (ext)
1109 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001110 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1111 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001112 ext = nid;
1113 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001114 }
1115 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001116 if (!ext && dock) {
1117 ext = dock;
1118 dock = 0;
1119 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001120 if (!ext || !fixed)
1121 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001122 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001123 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001124 if (dock && !is_jack_detectable(codec, dock))
1125 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001126
1127 /* check imux indices */
1128 spec->ext_mic_pin = ext;
1129 spec->int_mic_pin = fixed;
1130 spec->dock_mic_pin = dock;
1131
1132 spec->auto_mic = 1;
1133 if (!alc_auto_mic_check_imux(codec))
1134 return;
1135
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001136 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1137 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001138 spec->unsol_event = alc_sku_unsol_event;
1139}
1140
Takashi Iwai1d045db2011-07-07 18:23:21 +02001141/* check the availabilities of auto-mute and auto-mic switches */
1142static void alc_auto_check_switches(struct hda_codec *codec)
1143{
1144 alc_init_auto_hp(codec);
1145 alc_init_auto_mic(codec);
1146}
1147
1148/*
1149 * Realtek SSID verification
1150 */
1151
David Henningsson90622912010-10-14 14:50:18 +02001152/* Could be any non-zero and even value. When used as fixup, tells
1153 * the driver to ignore any present sku defines.
1154 */
1155#define ALC_FIXUP_SKU_IGNORE (2)
1156
Kailang Yangda00c242010-03-19 11:23:45 +01001157static int alc_auto_parse_customize_define(struct hda_codec *codec)
1158{
1159 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001160 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001161 struct alc_spec *spec = codec->spec;
1162
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001163 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1164
David Henningsson90622912010-10-14 14:50:18 +02001165 if (spec->cdefine.fixup) {
1166 ass = spec->cdefine.sku_cfg;
1167 if (ass == ALC_FIXUP_SKU_IGNORE)
1168 return -1;
1169 goto do_sku;
1170 }
1171
Kailang Yangda00c242010-03-19 11:23:45 +01001172 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001173 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001174 goto do_sku;
1175
1176 nid = 0x1d;
1177 if (codec->vendor_id == 0x10ec0260)
1178 nid = 0x17;
1179 ass = snd_hda_codec_get_pincfg(codec, nid);
1180
1181 if (!(ass & 1)) {
1182 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1183 codec->chip_name, ass);
1184 return -1;
1185 }
1186
1187 /* check sum */
1188 tmp = 0;
1189 for (i = 1; i < 16; i++) {
1190 if ((ass >> i) & 1)
1191 tmp++;
1192 }
1193 if (((ass >> 16) & 0xf) != tmp)
1194 return -1;
1195
1196 spec->cdefine.port_connectivity = ass >> 30;
1197 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1198 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1199 spec->cdefine.customization = ass >> 8;
1200do_sku:
1201 spec->cdefine.sku_cfg = ass;
1202 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1203 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1204 spec->cdefine.swap = (ass & 0x2) >> 1;
1205 spec->cdefine.override = ass & 0x1;
1206
1207 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1208 nid, spec->cdefine.sku_cfg);
1209 snd_printd("SKU: port_connectivity=0x%x\n",
1210 spec->cdefine.port_connectivity);
1211 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1212 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1213 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1214 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1215 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1216 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1217 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1218
1219 return 0;
1220}
1221
Takashi Iwai1d045db2011-07-07 18:23:21 +02001222/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001223static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1224{
Takashi Iwai21268962011-07-07 15:01:13 +02001225 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001226}
1227
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001228/* check subsystem ID and set up device-specific initialization;
1229 * return 1 if initialized, 0 if invalid SSID
1230 */
1231/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1232 * 31 ~ 16 : Manufacture ID
1233 * 15 ~ 8 : SKU ID
1234 * 7 ~ 0 : Assembly ID
1235 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1236 */
1237static int alc_subsystem_id(struct hda_codec *codec,
1238 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001239 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001240{
1241 unsigned int ass, tmp, i;
1242 unsigned nid;
1243 struct alc_spec *spec = codec->spec;
1244
David Henningsson90622912010-10-14 14:50:18 +02001245 if (spec->cdefine.fixup) {
1246 ass = spec->cdefine.sku_cfg;
1247 if (ass == ALC_FIXUP_SKU_IGNORE)
1248 return 0;
1249 goto do_sku;
1250 }
1251
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001252 ass = codec->subsystem_id & 0xffff;
1253 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1254 goto do_sku;
1255
1256 /* invalid SSID, check the special NID pin defcfg instead */
1257 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001258 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001259 * 29~21 : reserve
1260 * 20 : PCBEEP input
1261 * 19~16 : Check sum (15:1)
1262 * 15~1 : Custom
1263 * 0 : override
1264 */
1265 nid = 0x1d;
1266 if (codec->vendor_id == 0x10ec0260)
1267 nid = 0x17;
1268 ass = snd_hda_codec_get_pincfg(codec, nid);
1269 snd_printd("realtek: No valid SSID, "
1270 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001271 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001272 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001273 return 0;
1274 if ((ass >> 30) != 1) /* no physical connection */
1275 return 0;
1276
1277 /* check sum */
1278 tmp = 0;
1279 for (i = 1; i < 16; i++) {
1280 if ((ass >> i) & 1)
1281 tmp++;
1282 }
1283 if (((ass >> 16) & 0xf) != tmp)
1284 return 0;
1285do_sku:
1286 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1287 ass & 0xffff, codec->vendor_id);
1288 /*
1289 * 0 : override
1290 * 1 : Swap Jack
1291 * 2 : 0 --> Desktop, 1 --> Laptop
1292 * 3~5 : External Amplifier control
1293 * 7~6 : Reserved
1294 */
1295 tmp = (ass & 0x38) >> 3; /* external Amp control */
1296 switch (tmp) {
1297 case 1:
1298 spec->init_amp = ALC_INIT_GPIO1;
1299 break;
1300 case 3:
1301 spec->init_amp = ALC_INIT_GPIO2;
1302 break;
1303 case 7:
1304 spec->init_amp = ALC_INIT_GPIO3;
1305 break;
1306 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001307 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001308 spec->init_amp = ALC_INIT_DEFAULT;
1309 break;
1310 }
1311
1312 /* is laptop or Desktop and enable the function "Mute internal speaker
1313 * when the external headphone out jack is plugged"
1314 */
1315 if (!(ass & 0x8000))
1316 return 1;
1317 /*
1318 * 10~8 : Jack location
1319 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1320 * 14~13: Resvered
1321 * 15 : 1 --> enable the function "Mute internal speaker
1322 * when the external headphone out jack is plugged"
1323 */
Takashi Iwai5fe6e012011-09-26 10:41:21 +02001324 if (!spec->autocfg.hp_pins[0] &&
1325 !(spec->autocfg.line_out_pins[0] &&
1326 spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001327 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001328 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1329 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001330 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001331 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001332 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001333 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001334 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001335 else if (tmp == 3)
1336 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001337 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001338 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001339 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1340 spec->autocfg.line_outs))
1341 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001342 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001343 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001344 return 1;
1345}
Kailang Yangea1fb292008-08-26 12:58:38 +02001346
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001347/* Check the validity of ALC subsystem-id
1348 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1349static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001350{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001351 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001352 struct alc_spec *spec = codec->spec;
1353 snd_printd("realtek: "
1354 "Enable default setup for auto mode as fallback\n");
1355 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001356 }
Takashi Iwai21268962011-07-07 15:01:13 +02001357}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001358
Takashi Iwai41e41f12005-06-08 14:48:49 +02001359/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001360 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001361 */
1362
1363struct alc_pincfg {
1364 hda_nid_t nid;
1365 u32 val;
1366};
1367
Todd Broche1eb5f12010-12-06 11:19:51 -08001368struct alc_model_fixup {
1369 const int id;
1370 const char *name;
1371};
1372
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001373struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001374 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001375 bool chained;
1376 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001377 union {
1378 unsigned int sku;
1379 const struct alc_pincfg *pins;
1380 const struct hda_verb *verbs;
1381 void (*func)(struct hda_codec *codec,
1382 const struct alc_fixup *fix,
1383 int action);
1384 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001385};
1386
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001387enum {
1388 ALC_FIXUP_INVALID,
1389 ALC_FIXUP_SKU,
1390 ALC_FIXUP_PINS,
1391 ALC_FIXUP_VERBS,
1392 ALC_FIXUP_FUNC,
1393};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001394
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001395enum {
1396 ALC_FIXUP_ACT_PRE_PROBE,
1397 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001398 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001399};
1400
1401static void alc_apply_fixup(struct hda_codec *codec, int action)
1402{
1403 struct alc_spec *spec = codec->spec;
1404 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001405#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001406 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001407#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001408 int depth = 0;
1409
1410 if (!spec->fixup_list)
1411 return;
1412
1413 while (id >= 0) {
1414 const struct alc_fixup *fix = spec->fixup_list + id;
1415 const struct alc_pincfg *cfg;
1416
1417 switch (fix->type) {
1418 case ALC_FIXUP_SKU:
1419 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1420 break;;
1421 snd_printdd(KERN_INFO "hda_codec: %s: "
1422 "Apply sku override for %s\n",
1423 codec->chip_name, modelname);
1424 spec->cdefine.sku_cfg = fix->v.sku;
1425 spec->cdefine.fixup = 1;
1426 break;
1427 case ALC_FIXUP_PINS:
1428 cfg = fix->v.pins;
1429 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1430 break;
1431 snd_printdd(KERN_INFO "hda_codec: %s: "
1432 "Apply pincfg for %s\n",
1433 codec->chip_name, modelname);
1434 for (; cfg->nid; cfg++)
1435 snd_hda_codec_set_pincfg(codec, cfg->nid,
1436 cfg->val);
1437 break;
1438 case ALC_FIXUP_VERBS:
1439 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1440 break;
1441 snd_printdd(KERN_INFO "hda_codec: %s: "
1442 "Apply fix-verbs for %s\n",
1443 codec->chip_name, modelname);
1444 add_verb(codec->spec, fix->v.verbs);
1445 break;
1446 case ALC_FIXUP_FUNC:
1447 if (!fix->v.func)
1448 break;
1449 snd_printdd(KERN_INFO "hda_codec: %s: "
1450 "Apply fix-func for %s\n",
1451 codec->chip_name, modelname);
1452 fix->v.func(codec, fix, action);
1453 break;
1454 default:
1455 snd_printk(KERN_ERR "hda_codec: %s: "
1456 "Invalid fixup type %d\n",
1457 codec->chip_name, fix->type);
1458 break;
1459 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001460 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001461 break;
1462 if (++depth > 10)
1463 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001464 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001465 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001466}
1467
Todd Broche1eb5f12010-12-06 11:19:51 -08001468static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001469 const struct alc_model_fixup *models,
1470 const struct snd_pci_quirk *quirk,
1471 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001472{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001473 struct alc_spec *spec = codec->spec;
1474 int id = -1;
1475 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001476
Todd Broche1eb5f12010-12-06 11:19:51 -08001477 if (codec->modelname && models) {
1478 while (models->name) {
1479 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001480 id = models->id;
1481 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001482 break;
1483 }
1484 models++;
1485 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001486 }
1487 if (id < 0) {
1488 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1489 if (quirk) {
1490 id = quirk->value;
1491#ifdef CONFIG_SND_DEBUG_VERBOSE
1492 name = quirk->name;
1493#endif
1494 }
1495 }
1496
1497 spec->fixup_id = id;
1498 if (id >= 0) {
1499 spec->fixup_list = fixlist;
1500 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001501 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001502}
1503
Takashi Iwai1d045db2011-07-07 18:23:21 +02001504/*
1505 * COEF access helper functions
1506 */
Kailang Yang274693f2009-12-03 10:07:50 +01001507static int alc_read_coef_idx(struct hda_codec *codec,
1508 unsigned int coef_idx)
1509{
1510 unsigned int val;
1511 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1512 coef_idx);
1513 val = snd_hda_codec_read(codec, 0x20, 0,
1514 AC_VERB_GET_PROC_COEF, 0);
1515 return val;
1516}
1517
Kailang Yang977ddd62010-09-15 10:02:29 +02001518static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1519 unsigned int coef_val)
1520{
1521 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1522 coef_idx);
1523 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1524 coef_val);
1525}
1526
Takashi Iwai1d045db2011-07-07 18:23:21 +02001527/*
1528 * Digital I/O handling
1529 */
1530
Takashi Iwai757899a2010-07-30 10:48:14 +02001531/* set right pin controls for digital I/O */
1532static void alc_auto_init_digital(struct hda_codec *codec)
1533{
1534 struct alc_spec *spec = codec->spec;
1535 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001536 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001537
1538 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1539 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001540 if (!pin)
1541 continue;
1542 snd_hda_codec_write(codec, pin, 0,
1543 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1544 if (!i)
1545 dac = spec->multiout.dig_out_nid;
1546 else
1547 dac = spec->slave_dig_outs[i - 1];
1548 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1549 continue;
1550 snd_hda_codec_write(codec, dac, 0,
1551 AC_VERB_SET_AMP_GAIN_MUTE,
1552 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001553 }
1554 pin = spec->autocfg.dig_in_pin;
1555 if (pin)
1556 snd_hda_codec_write(codec, pin, 0,
1557 AC_VERB_SET_PIN_WIDGET_CONTROL,
1558 PIN_IN);
1559}
1560
1561/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1562static void alc_auto_parse_digital(struct hda_codec *codec)
1563{
1564 struct alc_spec *spec = codec->spec;
1565 int i, err;
1566 hda_nid_t dig_nid;
1567
1568 /* support multiple SPDIFs; the secondary is set up as a slave */
1569 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001570 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001571 err = snd_hda_get_connections(codec,
1572 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001573 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001574 if (err < 0)
1575 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001576 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001577 if (!i) {
1578 spec->multiout.dig_out_nid = dig_nid;
1579 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1580 } else {
1581 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1582 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1583 break;
1584 spec->slave_dig_outs[i - 1] = dig_nid;
1585 }
1586 }
1587
1588 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001589 dig_nid = codec->start_nid;
1590 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1591 unsigned int wcaps = get_wcaps(codec, dig_nid);
1592 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1593 continue;
1594 if (!(wcaps & AC_WCAP_DIGITAL))
1595 continue;
1596 if (!(wcaps & AC_WCAP_CONN_LIST))
1597 continue;
1598 err = get_connection_index(codec, dig_nid,
1599 spec->autocfg.dig_in_pin);
1600 if (err >= 0) {
1601 spec->dig_in_nid = dig_nid;
1602 break;
1603 }
1604 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001605 }
1606}
1607
Takashi Iwaif95474e2007-07-10 00:47:43 +02001608/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001609 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001610 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001611static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1612 struct snd_ctl_elem_info *uinfo)
1613{
1614 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1615 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001616 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001617 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001618
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001619 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001620 if (spec->vol_in_capsrc)
1621 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1622 else
1623 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1624 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001625 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001626 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001627 return err;
1628}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001630static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1631 unsigned int size, unsigned int __user *tlv)
1632{
1633 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1634 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001635 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001636 int err;
1637
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001638 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001639 if (spec->vol_in_capsrc)
1640 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1641 else
1642 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1643 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001644 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001645 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001646 return err;
1647}
1648
1649typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1650 struct snd_ctl_elem_value *ucontrol);
1651
1652static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1653 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001654 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001655{
1656 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1657 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001658 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001659
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001660 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001661 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001662 for (i = 0; i < spec->num_adc_nids; i++) {
1663 kcontrol->private_value =
1664 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1665 3, 0, HDA_INPUT);
1666 err = func(kcontrol, ucontrol);
1667 if (err < 0)
1668 goto error;
1669 }
1670 } else {
1671 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001672 if (spec->vol_in_capsrc)
1673 kcontrol->private_value =
1674 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1675 3, 0, HDA_OUTPUT);
1676 else
1677 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001678 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1679 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001680 err = func(kcontrol, ucontrol);
1681 }
1682 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001683 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001684 return err;
1685}
1686
1687static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1688 struct snd_ctl_elem_value *ucontrol)
1689{
1690 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001691 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001692}
1693
1694static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1695 struct snd_ctl_elem_value *ucontrol)
1696{
1697 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001698 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001699}
1700
1701/* capture mixer elements */
1702#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1703
1704static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1705 struct snd_ctl_elem_value *ucontrol)
1706{
1707 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001708 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001709}
1710
1711static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1712 struct snd_ctl_elem_value *ucontrol)
1713{
1714 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001715 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001716}
1717
Takashi Iwaia23b6882009-03-23 15:21:36 +01001718#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001719 { \
1720 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1721 .name = "Capture Switch", \
1722 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1723 .count = num, \
1724 .info = alc_cap_sw_info, \
1725 .get = alc_cap_sw_get, \
1726 .put = alc_cap_sw_put, \
1727 }, \
1728 { \
1729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1730 .name = "Capture Volume", \
1731 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1732 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1733 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1734 .count = num, \
1735 .info = alc_cap_vol_info, \
1736 .get = alc_cap_vol_get, \
1737 .put = alc_cap_vol_put, \
1738 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001739 }
1740
1741#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001742 { \
1743 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1744 /* .name = "Capture Source", */ \
1745 .name = "Input Source", \
1746 .count = num, \
1747 .info = alc_mux_enum_info, \
1748 .get = alc_mux_enum_get, \
1749 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001750 }
1751
1752#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001753static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001754 _DEFINE_CAPMIX(num), \
1755 _DEFINE_CAPSRC(num), \
1756 { } /* end */ \
1757}
1758
1759#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001760static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001761 _DEFINE_CAPMIX(num), \
1762 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001763}
1764
1765/* up to three ADCs */
1766DEFINE_CAPMIX(1);
1767DEFINE_CAPMIX(2);
1768DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001769DEFINE_CAPMIX_NOSRC(1);
1770DEFINE_CAPMIX_NOSRC(2);
1771DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001772
1773/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001774 * virtual master controls
1775 */
1776
1777/*
1778 * slave controls for virtual master
1779 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001780static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001781 "Front Playback Volume",
1782 "Surround Playback Volume",
1783 "Center Playback Volume",
1784 "LFE Playback Volume",
1785 "Side Playback Volume",
1786 "Headphone Playback Volume",
1787 "Speaker Playback Volume",
1788 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001789 "Line-Out Playback Volume",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001790 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001791 NULL,
1792};
1793
Takashi Iwaiea734962011-01-17 11:29:34 +01001794static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001795 "Front Playback Switch",
1796 "Surround Playback Switch",
1797 "Center Playback Switch",
1798 "LFE Playback Switch",
1799 "Side Playback Switch",
1800 "Headphone Playback Switch",
1801 "Speaker Playback Switch",
1802 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001803 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001804 "Line-Out Playback Switch",
Takashi Iwai3fe45ae2011-08-18 15:13:17 +02001805 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001806 NULL,
1807};
1808
1809/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001810 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001812
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001813#define NID_MAPPING (-1)
1814
1815#define SUBDEV_SPEAKER_ (0 << 6)
1816#define SUBDEV_HP_ (1 << 6)
1817#define SUBDEV_LINE_ (2 << 6)
1818#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1819#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1820#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1821
Takashi Iwai603c4012008-07-30 15:01:44 +02001822static void alc_free_kctls(struct hda_codec *codec);
1823
Takashi Iwai67d634c2009-11-16 15:35:59 +01001824#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001825/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001826static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001827 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001828 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001829 { } /* end */
1830};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001831#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001832
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833static int alc_build_controls(struct hda_codec *codec)
1834{
1835 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001836 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001837 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001838 int i, j, err;
1839 unsigned int u;
1840 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841
1842 for (i = 0; i < spec->num_mixers; i++) {
1843 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1844 if (err < 0)
1845 return err;
1846 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001847 if (spec->cap_mixer) {
1848 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1849 if (err < 0)
1850 return err;
1851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001853 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001854 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001855 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 if (err < 0)
1857 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001858 if (!spec->no_analog) {
1859 err = snd_hda_create_spdif_share_sw(codec,
1860 &spec->multiout);
1861 if (err < 0)
1862 return err;
1863 spec->multiout.share_spdif = 1;
1864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 }
1866 if (spec->dig_in_nid) {
1867 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1868 if (err < 0)
1869 return err;
1870 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001871
Takashi Iwai67d634c2009-11-16 15:35:59 +01001872#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001873 /* create beep controls if needed */
1874 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001875 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001876 for (knew = alc_beep_mixer; knew->name; knew++) {
1877 struct snd_kcontrol *kctl;
1878 kctl = snd_ctl_new1(knew, codec);
1879 if (!kctl)
1880 return -ENOMEM;
1881 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001882 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001883 if (err < 0)
1884 return err;
1885 }
1886 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001887#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001888
Takashi Iwai2134ea42008-01-10 16:53:55 +01001889 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001890 if (!spec->no_analog &&
1891 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001892 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001893 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001894 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001895 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001896 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001897 if (err < 0)
1898 return err;
1899 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001900 if (!spec->no_analog &&
1901 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001902 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1903 NULL, alc_slave_sws);
1904 if (err < 0)
1905 return err;
1906 }
1907
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001908 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001909 if (spec->capsrc_nids || spec->adc_nids) {
1910 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1911 if (!kctl)
1912 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1913 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001914 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001915 if (!nids)
1916 nids = spec->adc_nids;
1917 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1918 if (err < 0)
1919 return err;
1920 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001921 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001922 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001923 const char *kname = kctl ? kctl->id.name : NULL;
1924 for (knew = spec->cap_mixer; knew->name; knew++) {
1925 if (kname && strcmp(knew->name, kname) == 0)
1926 continue;
1927 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1928 for (i = 0; kctl && i < kctl->count; i++) {
1929 err = snd_hda_add_nid(codec, kctl, i,
1930 spec->adc_nids[i]);
1931 if (err < 0)
1932 return err;
1933 }
1934 }
1935 }
1936
1937 /* other nid->control mapping */
1938 for (i = 0; i < spec->num_mixers; i++) {
1939 for (knew = spec->mixers[i]; knew->name; knew++) {
1940 if (knew->iface != NID_MAPPING)
1941 continue;
1942 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1943 if (kctl == NULL)
1944 continue;
1945 u = knew->subdevice;
1946 for (j = 0; j < 4; j++, u >>= 8) {
1947 nid = u & 0x3f;
1948 if (nid == 0)
1949 continue;
1950 switch (u & 0xc0) {
1951 case SUBDEV_SPEAKER_:
1952 nid = spec->autocfg.speaker_pins[nid];
1953 break;
1954 case SUBDEV_LINE_:
1955 nid = spec->autocfg.line_out_pins[nid];
1956 break;
1957 case SUBDEV_HP_:
1958 nid = spec->autocfg.hp_pins[nid];
1959 break;
1960 default:
1961 continue;
1962 }
1963 err = snd_hda_add_nid(codec, kctl, 0, nid);
1964 if (err < 0)
1965 return err;
1966 }
1967 u = knew->private_value;
1968 for (j = 0; j < 4; j++, u >>= 8) {
1969 nid = u & 0xff;
1970 if (nid == 0)
1971 continue;
1972 err = snd_hda_add_nid(codec, kctl, 0, nid);
1973 if (err < 0)
1974 return err;
1975 }
1976 }
1977 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001978
1979 alc_free_kctls(codec); /* no longer needed */
1980
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 return 0;
1982}
1983
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001984
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001986 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001987 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001988
Takashi Iwai584c0c42011-03-10 12:51:11 +01001989static void alc_init_special_input_src(struct hda_codec *codec);
1990
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991static int alc_init(struct hda_codec *codec)
1992{
1993 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001994 unsigned int i;
1995
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001996 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001997 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02001998
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001999 for (i = 0; i < spec->num_init_verbs; i++)
2000 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01002001 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002002
2003 if (spec->init_hook)
2004 spec->init_hook(codec);
2005
Takashi Iwai58701122011-01-13 15:41:45 +01002006 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2007
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002008 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 return 0;
2010}
2011
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002012static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2013{
2014 struct alc_spec *spec = codec->spec;
2015
2016 if (spec->unsol_event)
2017 spec->unsol_event(codec, res);
2018}
2019
Takashi Iwaicb53c622007-08-10 17:21:45 +02002020#ifdef CONFIG_SND_HDA_POWER_SAVE
2021static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2022{
2023 struct alc_spec *spec = codec->spec;
2024 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2025}
2026#endif
2027
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028/*
2029 * Analog playback callbacks
2030 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002031static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002033 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034{
2035 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002036 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2037 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038}
2039
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002040static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 struct hda_codec *codec,
2042 unsigned int stream_tag,
2043 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002044 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045{
2046 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002047 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2048 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049}
2050
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002051static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002053 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054{
2055 struct alc_spec *spec = codec->spec;
2056 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2057}
2058
2059/*
2060 * Digital out
2061 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002062static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002064 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065{
2066 struct alc_spec *spec = codec->spec;
2067 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2068}
2069
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002070static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002071 struct hda_codec *codec,
2072 unsigned int stream_tag,
2073 unsigned int format,
2074 struct snd_pcm_substream *substream)
2075{
2076 struct alc_spec *spec = codec->spec;
2077 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2078 stream_tag, format, substream);
2079}
2080
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002081static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002082 struct hda_codec *codec,
2083 struct snd_pcm_substream *substream)
2084{
2085 struct alc_spec *spec = codec->spec;
2086 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2087}
2088
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002089static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002091 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092{
2093 struct alc_spec *spec = codec->spec;
2094 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2095}
2096
2097/*
2098 * Analog capture
2099 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002100static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 struct hda_codec *codec,
2102 unsigned int stream_tag,
2103 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002104 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105{
2106 struct alc_spec *spec = codec->spec;
2107
Takashi Iwai63300792008-01-24 15:31:36 +01002108 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 stream_tag, 0, format);
2110 return 0;
2111}
2112
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002113static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002115 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116{
2117 struct alc_spec *spec = codec->spec;
2118
Takashi Iwai888afa12008-03-18 09:57:50 +01002119 snd_hda_codec_cleanup_stream(codec,
2120 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 return 0;
2122}
2123
Takashi Iwai840b64c2010-07-13 22:49:01 +02002124/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002125static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002126 struct hda_codec *codec,
2127 unsigned int stream_tag,
2128 unsigned int format,
2129 struct snd_pcm_substream *substream)
2130{
2131 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002132 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002133 spec->cur_adc_stream_tag = stream_tag;
2134 spec->cur_adc_format = format;
2135 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2136 return 0;
2137}
2138
Takashi Iwai21268962011-07-07 15:01:13 +02002139static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002140 struct hda_codec *codec,
2141 struct snd_pcm_substream *substream)
2142{
2143 struct alc_spec *spec = codec->spec;
2144 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2145 spec->cur_adc = 0;
2146 return 0;
2147}
2148
Takashi Iwai21268962011-07-07 15:01:13 +02002149static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002150 .substreams = 1,
2151 .channels_min = 2,
2152 .channels_max = 2,
2153 .nid = 0, /* fill later */
2154 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002155 .prepare = dyn_adc_capture_pcm_prepare,
2156 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002157 },
2158};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160/*
2161 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002162static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 .substreams = 1,
2164 .channels_min = 2,
2165 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002166 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002168 .open = alc_playback_pcm_open,
2169 .prepare = alc_playback_pcm_prepare,
2170 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 },
2172};
2173
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002174static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002175 .substreams = 1,
2176 .channels_min = 2,
2177 .channels_max = 2,
2178 /* NID is set in alc_build_pcms */
2179};
2180
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002181static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002182 .substreams = 1,
2183 .channels_min = 2,
2184 .channels_max = 2,
2185 /* NID is set in alc_build_pcms */
2186};
2187
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002188static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002189 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 .channels_min = 2,
2191 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002192 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002194 .prepare = alc_alt_capture_pcm_prepare,
2195 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 },
2197};
2198
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002199static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 .substreams = 1,
2201 .channels_min = 2,
2202 .channels_max = 2,
2203 /* NID is set in alc_build_pcms */
2204 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002205 .open = alc_dig_playback_pcm_open,
2206 .close = alc_dig_playback_pcm_close,
2207 .prepare = alc_dig_playback_pcm_prepare,
2208 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 },
2210};
2211
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002212static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 .substreams = 1,
2214 .channels_min = 2,
2215 .channels_max = 2,
2216 /* NID is set in alc_build_pcms */
2217};
2218
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002219/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002220static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002221 .substreams = 0,
2222 .channels_min = 0,
2223 .channels_max = 0,
2224};
2225
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226static int alc_build_pcms(struct hda_codec *codec)
2227{
2228 struct alc_spec *spec = codec->spec;
2229 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002230 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 int i;
2232
2233 codec->num_pcms = 1;
2234 codec->pcm_info = info;
2235
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002236 if (spec->no_analog)
2237 goto skip_analog;
2238
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002239 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2240 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002242
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002243 if (spec->multiout.dac_nids > 0) {
2244 p = spec->stream_analog_playback;
2245 if (!p)
2246 p = &alc_pcm_analog_playback;
2247 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002248 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2249 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002250 if (spec->adc_nids) {
2251 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002252 if (!p) {
2253 if (spec->dyn_adc_switch)
2254 p = &dyn_adc_pcm_analog_capture;
2255 else
2256 p = &alc_pcm_analog_capture;
2257 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002258 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002259 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261
Takashi Iwai4a471b72005-12-07 13:56:29 +01002262 if (spec->channel_mode) {
2263 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2264 for (i = 0; i < spec->num_channel_mode; i++) {
2265 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2266 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 }
2269 }
2270
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002271 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002272 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002274 snprintf(spec->stream_name_digital,
2275 sizeof(spec->stream_name_digital),
2276 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002277 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002278 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002279 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002281 if (spec->dig_out_type)
2282 info->pcm_type = spec->dig_out_type;
2283 else
2284 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002285 if (spec->multiout.dig_out_nid) {
2286 p = spec->stream_digital_playback;
2287 if (!p)
2288 p = &alc_pcm_digital_playback;
2289 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2291 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002292 if (spec->dig_in_nid) {
2293 p = spec->stream_digital_capture;
2294 if (!p)
2295 p = &alc_pcm_digital_capture;
2296 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2298 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002299 /* FIXME: do we need this for all Realtek codec models? */
2300 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 }
2302
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002303 if (spec->no_analog)
2304 return 0;
2305
Takashi Iwaie08a0072006-09-07 17:52:14 +02002306 /* If the use of more than one ADC is requested for the current
2307 * model, configure a second analog capture-only PCM.
2308 */
2309 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002310 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002311 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002312 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002313 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002314 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002315 p = spec->stream_analog_alt_playback;
2316 if (!p)
2317 p = &alc_pcm_analog_alt_playback;
2318 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002319 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2320 spec->alt_dac_nid;
2321 } else {
2322 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2323 alc_pcm_null_stream;
2324 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2325 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002326 if (spec->num_adc_nids > 1) {
2327 p = spec->stream_analog_alt_capture;
2328 if (!p)
2329 p = &alc_pcm_analog_alt_capture;
2330 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002331 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2332 spec->adc_nids[1];
2333 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2334 spec->num_adc_nids - 1;
2335 } else {
2336 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2337 alc_pcm_null_stream;
2338 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002339 }
2340 }
2341
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 return 0;
2343}
2344
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002345static inline void alc_shutup(struct hda_codec *codec)
2346{
Takashi Iwai1c7161532011-04-07 10:37:16 +02002347 struct alc_spec *spec = codec->spec;
2348
2349 if (spec && spec->shutup)
2350 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002351 snd_hda_shutup_pins(codec);
2352}
2353
Takashi Iwai603c4012008-07-30 15:01:44 +02002354static void alc_free_kctls(struct hda_codec *codec)
2355{
2356 struct alc_spec *spec = codec->spec;
2357
2358 if (spec->kctls.list) {
2359 struct snd_kcontrol_new *kctl = spec->kctls.list;
2360 int i;
2361 for (i = 0; i < spec->kctls.used; i++)
2362 kfree(kctl[i].name);
2363 }
2364 snd_array_free(&spec->kctls);
2365}
2366
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367static void alc_free(struct hda_codec *codec)
2368{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002369 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002370
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002371 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002372 return;
2373
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002374 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002375 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002376 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002377 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002378 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379}
2380
Hector Martinf5de24b2009-12-20 22:51:31 +01002381#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002382static void alc_power_eapd(struct hda_codec *codec)
2383{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002384 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002385}
2386
Hector Martinf5de24b2009-12-20 22:51:31 +01002387static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2388{
2389 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002390 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002391 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002392 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002393 return 0;
2394}
2395#endif
2396
Takashi Iwai2a439522011-07-26 09:52:50 +02002397#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002398static int alc_resume(struct hda_codec *codec)
2399{
Takashi Iwai1c7161532011-04-07 10:37:16 +02002400 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002401 codec->patch_ops.init(codec);
2402 snd_hda_codec_resume_amp(codec);
2403 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002404 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002405 return 0;
2406}
Takashi Iwaie044c392008-10-27 16:56:24 +01002407#endif
2408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409/*
2410 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002411static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 .build_controls = alc_build_controls,
2413 .build_pcms = alc_build_pcms,
2414 .init = alc_init,
2415 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002416 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002417#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002418 .resume = alc_resume,
2419#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002420#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002421 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002422 .check_power_status = alc_check_power_status,
2423#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002424 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425};
2426
Kailang Yangc027ddc2010-03-19 11:33:06 +01002427/* replace the codec chip_name with the given string */
2428static int alc_codec_rename(struct hda_codec *codec, const char *name)
2429{
2430 kfree(codec->chip_name);
2431 codec->chip_name = kstrdup(name, GFP_KERNEL);
2432 if (!codec->chip_name) {
2433 alc_free(codec);
2434 return -ENOMEM;
2435 }
2436 return 0;
2437}
2438
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002439/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002440 * Automatic parse of I/O pins from the BIOS configuration
2441 */
2442
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002443enum {
2444 ALC_CTL_WIDGET_VOL,
2445 ALC_CTL_WIDGET_MUTE,
2446 ALC_CTL_BIND_MUTE,
2447};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002448static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002449 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2450 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002451 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002452};
2453
2454/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002455static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002456 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002457{
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002458 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002459
Takashi Iwaice764ab2011-04-27 16:35:23 +02002460 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002461 if (!knew)
2462 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002463 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002464 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002465 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002466 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002467 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002468 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002469 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002470 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002471 return 0;
2472}
2473
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002474static int add_control_with_pfx(struct alc_spec *spec, int type,
2475 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002476 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002477{
2478 char name[32];
2479 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002480 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002481}
2482
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002483#define add_pb_vol_ctrl(spec, type, pfx, val) \
2484 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2485#define add_pb_sw_ctrl(spec, type, pfx, val) \
2486 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2487#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2488 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2489#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2490 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002491
Takashi Iwai6843ca12011-06-24 11:03:58 +02002492static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2493 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002494{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002495 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002496 static const char * const chname[4] = {
2497 "Front", "Surround", NULL /*CLFE*/, "Side"
2498 };
Takashi Iwaice764ab2011-04-27 16:35:23 +02002499
Takashi Iwai6843ca12011-06-24 11:03:58 +02002500 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002501 if (cfg->line_outs == 1 && !spec->multi_ios &&
2502 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002503 return "Master";
2504
2505 switch (cfg->line_out_type) {
2506 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002507 if (cfg->line_outs == 1)
2508 return "Speaker";
2509 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002510 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002511 /* for multi-io case, only the primary out */
2512 if (ch && spec->multi_ios)
2513 break;
2514 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002515 return "Headphone";
2516 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002517 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002518 return "PCM";
2519 break;
2520 }
Takashi Iwai6843ca12011-06-24 11:03:58 +02002521 return chname[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002522}
2523
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002524/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002525static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002526 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002527 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002528{
Kailang Yangdf694da2005-12-05 19:42:22 +01002529 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002530
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002531 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002532 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2533 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002534 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002535 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002536 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2537 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002538 return err;
2539 return 0;
2540}
2541
Takashi Iwai05f5f472009-08-25 13:10:18 +02002542static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002543{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002544 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2545 return (pincap & AC_PINCAP_IN) != 0;
2546}
2547
Takashi Iwai1d045db2011-07-07 18:23:21 +02002548/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002549static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002550{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002551 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002552 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002553 hda_nid_t *adc_nids = spec->private_adc_nids;
2554 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2555 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2556 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002557 int i, nums = 0;
2558
2559 nid = codec->start_nid;
2560 for (i = 0; i < codec->num_nodes; i++, nid++) {
2561 hda_nid_t src;
2562 const hda_nid_t *list;
2563 unsigned int caps = get_wcaps(codec, nid);
2564 int type = get_wcaps_type(caps);
2565
2566 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2567 continue;
2568 adc_nids[nums] = nid;
2569 cap_nids[nums] = nid;
2570 src = nid;
2571 for (;;) {
2572 int n;
2573 type = get_wcaps_type(get_wcaps(codec, src));
2574 if (type == AC_WID_PIN)
2575 break;
2576 if (type == AC_WID_AUD_SEL) {
2577 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002578 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002579 break;
2580 }
2581 n = snd_hda_get_conn_list(codec, src, &list);
2582 if (n > 1) {
2583 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002584 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002585 break;
2586 } else if (n != 1)
2587 break;
2588 src = *list;
2589 }
2590 if (++nums >= max_nums)
2591 break;
2592 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002593 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002594 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002595 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002596 return nums;
2597}
2598
Takashi Iwai05f5f472009-08-25 13:10:18 +02002599/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002600static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002601{
2602 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002603 const struct auto_pin_cfg *cfg = &spec->autocfg;
2604 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002605 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002606 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002607 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002608 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002609
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002610 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002611 if (num_adcs < 0)
2612 return 0;
2613
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002614 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002615 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002616 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002617
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002618 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002619 if (!alc_is_input_pin(codec, pin))
2620 continue;
2621
David Henningsson5322bf22011-01-05 11:03:56 +01002622 label = hda_get_autocfg_input_label(codec, cfg, i);
2623 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002624 type_idx++;
2625 else
2626 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002627 prev_label = label;
2628
Takashi Iwai05f5f472009-08-25 13:10:18 +02002629 if (mixer) {
2630 idx = get_connection_index(codec, mixer, pin);
2631 if (idx >= 0) {
2632 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002633 label, type_idx,
2634 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002635 if (err < 0)
2636 return err;
2637 }
2638 }
2639
Takashi Iwaib7821702011-07-06 15:12:46 +02002640 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002641 hda_nid_t cap = spec->capsrc_nids ?
2642 spec->capsrc_nids[c] : spec->adc_nids[c];
2643 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002644 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002645 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002646 snd_hda_add_imux_item(imux, label, idx, NULL);
2647 break;
2648 }
2649 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002650 }
Takashi Iwai21268962011-07-07 15:01:13 +02002651
2652 spec->num_mux_defs = 1;
2653 spec->input_mux = imux;
2654
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002655 return 0;
2656}
2657
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002658static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2659 unsigned int pin_type)
2660{
2661 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2662 pin_type);
2663 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002664 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2665 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002666 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002667}
2668
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002669static int get_pin_type(int line_out_type)
2670{
2671 if (line_out_type == AUTO_PIN_HP_OUT)
2672 return PIN_HP;
2673 else
2674 return PIN_OUT;
2675}
2676
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002677static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002678{
2679 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002680 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002681 int i;
2682
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002683 for (i = 0; i < cfg->num_inputs; i++) {
2684 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002685 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002686 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002687 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002688 snd_hda_codec_write(codec, nid, 0,
2689 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002690 AMP_OUT_MUTE);
2691 }
2692 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002693
2694 /* mute all loopback inputs */
2695 if (spec->mixer_nid) {
2696 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2697 for (i = 0; i < nums; i++)
2698 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2699 AC_VERB_SET_AMP_GAIN_MUTE,
2700 AMP_IN_MUTE(i));
2701 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002702}
2703
Takashi Iwai7085ec12009-10-02 09:03:58 +02002704/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002705static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002706{
Takashi Iwai604401a2011-04-27 15:14:23 +02002707 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002708 int i, num;
2709
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002710 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2711 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002712 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2713 for (i = 0; i < num; i++) {
2714 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2715 return list[i];
2716 }
2717 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002718}
2719
Takashi Iwai604401a2011-04-27 15:14:23 +02002720/* go down to the selector widget before the mixer */
2721static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2722{
2723 hda_nid_t srcs[5];
2724 int num = snd_hda_get_connections(codec, pin, srcs,
2725 ARRAY_SIZE(srcs));
2726 if (num != 1 ||
2727 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2728 return pin;
2729 return srcs[0];
2730}
2731
Takashi Iwai7085ec12009-10-02 09:03:58 +02002732/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002733static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002734 hda_nid_t dac)
2735{
David Henningssoncc1c4522010-11-24 14:17:47 +01002736 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002737 int i, num;
2738
Takashi Iwai604401a2011-04-27 15:14:23 +02002739 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002740 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2741 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002742 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002743 return mix[i];
2744 }
2745 return 0;
2746}
2747
Takashi Iwaice764ab2011-04-27 16:35:23 +02002748/* select the connection from pin to DAC if needed */
2749static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2750 hda_nid_t dac)
2751{
2752 hda_nid_t mix[5];
2753 int i, num;
2754
2755 pin = alc_go_down_to_selector(codec, pin);
2756 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2757 if (num < 2)
2758 return 0;
2759 for (i = 0; i < num; i++) {
2760 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2761 snd_hda_codec_update_cache(codec, pin, 0,
2762 AC_VERB_SET_CONNECT_SEL, i);
2763 return 0;
2764 }
2765 }
2766 return 0;
2767}
2768
Takashi Iwai7085ec12009-10-02 09:03:58 +02002769/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002770static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002771{
2772 struct alc_spec *spec = codec->spec;
2773 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002774 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002775
Takashi Iwai604401a2011-04-27 15:14:23 +02002776 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002777 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002778 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002779 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002780 if (!nid)
2781 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002782 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2783 spec->multiout.num_dacs))
2784 continue;
2785 if (spec->multiout.hp_nid == nid)
2786 continue;
2787 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2788 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2789 continue;
2790 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002791 }
2792 return 0;
2793}
2794
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002795static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2796{
2797 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2798 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2799 return alc_auto_look_for_dac(codec, pin);
2800 return 0;
2801}
2802
Takashi Iwai7085ec12009-10-02 09:03:58 +02002803/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002804static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002805{
2806 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002807 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002808 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002809 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002810
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002811 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002812 /* set num_dacs once to full for alc_auto_look_for_dac() */
2813 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002814 spec->multiout.hp_nid = 0;
2815 spec->multiout.extra_out_nid[0] = 0;
2816 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2817 spec->multiout.dac_nids = spec->private_dac_nids;
2818
2819 /* fill hard-wired DACs first */
2820 if (!redone) {
2821 for (i = 0; i < cfg->line_outs; i++)
2822 spec->private_dac_nids[i] =
2823 get_dac_if_single(codec, cfg->line_out_pins[i]);
2824 if (cfg->hp_outs)
2825 spec->multiout.hp_nid =
2826 get_dac_if_single(codec, cfg->hp_pins[0]);
2827 if (cfg->speaker_outs)
2828 spec->multiout.extra_out_nid[0] =
2829 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002830 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002831
2832 for (i = 0; i < cfg->line_outs; i++) {
2833 hda_nid_t pin = cfg->line_out_pins[i];
2834 if (spec->private_dac_nids[i])
2835 continue;
2836 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2837 if (!spec->private_dac_nids[i] && !redone) {
2838 /* if we can't find primary DACs, re-probe without
2839 * checking the hard-wired DACs
2840 */
2841 redone = true;
2842 goto again;
2843 }
2844 }
2845
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002846 /* re-count num_dacs and squash invalid entries */
2847 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002848 for (i = 0; i < cfg->line_outs; i++) {
2849 if (spec->private_dac_nids[i])
2850 spec->multiout.num_dacs++;
2851 else
2852 memmove(spec->private_dac_nids + i,
2853 spec->private_dac_nids + i + 1,
2854 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2855 }
2856
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002857 if (cfg->hp_outs && !spec->multiout.hp_nid)
2858 spec->multiout.hp_nid =
2859 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2860 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2861 spec->multiout.extra_out_nid[0] =
2862 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2863
Takashi Iwai7085ec12009-10-02 09:03:58 +02002864 return 0;
2865}
2866
Takashi Iwai343a04b2011-07-06 14:28:39 +02002867static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002868 const char *pfx, int cidx,
2869 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002870{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002871 if (!nid)
2872 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002873 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2874 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002875}
2876
Takashi Iwai343a04b2011-07-06 14:28:39 +02002877#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2878 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002879
2880/* create a mute-switch for the given mixer widget;
2881 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2882 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002883static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002884 const char *pfx, int cidx,
2885 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002886{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002887 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002888 int type;
2889 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002890 if (!nid)
2891 return 0;
2892 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2893 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2894 type = ALC_CTL_WIDGET_MUTE;
2895 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2896 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002897 type = ALC_CTL_WIDGET_MUTE;
2898 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2899 } else {
2900 type = ALC_CTL_BIND_MUTE;
2901 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2902 }
2903 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002904}
2905
Takashi Iwai343a04b2011-07-06 14:28:39 +02002906#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2907 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002908
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002909static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2910 hda_nid_t pin, hda_nid_t dac)
2911{
2912 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2913 if (nid_has_mute(codec, pin, HDA_OUTPUT))
2914 return pin;
2915 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
2916 return mix;
2917 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
2918 return dac;
2919 return 0;
2920}
2921
2922static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
2923 hda_nid_t pin, hda_nid_t dac)
2924{
2925 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2926 if (nid_has_volume(codec, dac, HDA_OUTPUT))
2927 return dac;
2928 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
2929 return mix;
2930 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
2931 return pin;
2932 return 0;
2933}
2934
Takashi Iwai7085ec12009-10-02 09:03:58 +02002935/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002936static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002937 const struct auto_pin_cfg *cfg)
2938{
2939 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002940 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002941
Takashi Iwaice764ab2011-04-27 16:35:23 +02002942 noutputs = cfg->line_outs;
2943 if (spec->multi_ios > 0)
2944 noutputs += spec->multi_ios;
2945
2946 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002947 const char *name;
2948 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002949 hda_nid_t dac, pin;
2950 hda_nid_t sw, vol;
2951
2952 dac = spec->multiout.dac_nids[i];
2953 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002954 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002955 if (i >= cfg->line_outs)
2956 pin = spec->multi_io[i - 1].pin;
2957 else
2958 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002959
2960 sw = alc_look_for_out_mute_nid(codec, pin, dac);
2961 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02002962 name = alc_get_line_out_pfx(spec, i, true, &index);
2963 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002964 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002965 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
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_vol_ctl(codec, "LFE", 0, vol, 2);
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, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002972 if (err < 0)
2973 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002974 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002975 if (err < 0)
2976 return err;
2977 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002978 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002979 if (err < 0)
2980 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002981 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002982 if (err < 0)
2983 return err;
2984 }
2985 }
2986 return 0;
2987}
2988
2989/* add playback controls for speaker and HP outputs */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002990static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002991 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002992{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002993 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002994 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002995 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002996
2997 if (!pin)
2998 return 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002999 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02003000 /* the corresponding DAC is already occupied */
3001 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
3002 return 0; /* no way */
3003 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02003004 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003005 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3006 }
3007
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003008 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3009 vol = alc_look_for_out_vol_nid(codec, pin, dac);
3010 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003011 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003012 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003013 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003014 if (err < 0)
3015 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003016 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003017}
3018
Takashi Iwai343a04b2011-07-06 14:28:39 +02003019static int alc_auto_create_hp_out(struct hda_codec *codec)
3020{
3021 struct alc_spec *spec = codec->spec;
3022 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3023 spec->multiout.hp_nid,
3024 "Headphone");
3025}
3026
3027static int alc_auto_create_speaker_out(struct hda_codec *codec)
3028{
3029 struct alc_spec *spec = codec->spec;
3030 return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
3031 spec->multiout.extra_out_nid[0],
3032 "Speaker");
3033}
3034
Takashi Iwai343a04b2011-07-06 14:28:39 +02003035static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003036 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003037 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003038{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003039 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003040 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003041 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003042
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003043 alc_set_pin_output(codec, pin, pin_type);
3044 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003045 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003046 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003047 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003048 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003049 mix = srcs[i];
3050 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003051 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003052 if (!mix)
3053 return;
3054
3055 /* need the manual connection? */
3056 if (num > 1)
3057 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3058 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003059 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3060 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003061 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003062 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003063 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003064 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003065 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003066 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3067 if (nid)
3068 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3069 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003070}
3071
Takashi Iwai343a04b2011-07-06 14:28:39 +02003072static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003073{
3074 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003075 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003076 int i;
3077
3078 for (i = 0; i <= HDA_SIDE; i++) {
3079 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3080 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003081 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003082 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003083 }
3084}
3085
Takashi Iwai343a04b2011-07-06 14:28:39 +02003086static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003087{
3088 struct alc_spec *spec = codec->spec;
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003089 hda_nid_t pin, dac;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003090
3091 pin = spec->autocfg.hp_pins[0];
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003092 if (pin) {
3093 dac = spec->multiout.hp_nid;
3094 if (!dac)
3095 dac = spec->multiout.dac_nids[0];
3096 alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
3097 }
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003098 pin = spec->autocfg.speaker_pins[0];
Takashi Iwai675c1aa2011-08-23 12:36:28 +02003099 if (pin) {
3100 dac = spec->multiout.extra_out_nid[0];
3101 if (!dac)
3102 dac = spec->multiout.dac_nids[0];
3103 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
3104 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003105}
3106
Takashi Iwaice764ab2011-04-27 16:35:23 +02003107/*
3108 * multi-io helper
3109 */
3110static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3111 unsigned int location)
3112{
3113 struct alc_spec *spec = codec->spec;
3114 struct auto_pin_cfg *cfg = &spec->autocfg;
3115 int type, i, num_pins = 0;
3116
3117 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3118 for (i = 0; i < cfg->num_inputs; i++) {
3119 hda_nid_t nid = cfg->inputs[i].pin;
3120 hda_nid_t dac;
3121 unsigned int defcfg, caps;
3122 if (cfg->inputs[i].type != type)
3123 continue;
3124 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3125 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3126 continue;
3127 if (location && get_defcfg_location(defcfg) != location)
3128 continue;
3129 caps = snd_hda_query_pin_caps(codec, nid);
3130 if (!(caps & AC_PINCAP_OUT))
3131 continue;
3132 dac = alc_auto_look_for_dac(codec, nid);
3133 if (!dac)
3134 continue;
3135 spec->multi_io[num_pins].pin = nid;
3136 spec->multi_io[num_pins].dac = dac;
3137 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003138 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003139 }
3140 }
3141 spec->multiout.num_dacs = 1;
3142 if (num_pins < 2)
3143 return 0;
3144 return num_pins;
3145}
3146
3147static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3148 struct snd_ctl_elem_info *uinfo)
3149{
3150 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3151 struct alc_spec *spec = codec->spec;
3152
3153 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3154 uinfo->count = 1;
3155 uinfo->value.enumerated.items = spec->multi_ios + 1;
3156 if (uinfo->value.enumerated.item > spec->multi_ios)
3157 uinfo->value.enumerated.item = spec->multi_ios;
3158 sprintf(uinfo->value.enumerated.name, "%dch",
3159 (uinfo->value.enumerated.item + 1) * 2);
3160 return 0;
3161}
3162
3163static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3164 struct snd_ctl_elem_value *ucontrol)
3165{
3166 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3167 struct alc_spec *spec = codec->spec;
3168 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3169 return 0;
3170}
3171
3172static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3173{
3174 struct alc_spec *spec = codec->spec;
3175 hda_nid_t nid = spec->multi_io[idx].pin;
3176
3177 if (!spec->multi_io[idx].ctl_in)
3178 spec->multi_io[idx].ctl_in =
3179 snd_hda_codec_read(codec, nid, 0,
3180 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3181 if (output) {
3182 snd_hda_codec_update_cache(codec, nid, 0,
3183 AC_VERB_SET_PIN_WIDGET_CONTROL,
3184 PIN_OUT);
3185 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3186 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3187 HDA_AMP_MUTE, 0);
3188 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3189 } else {
3190 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3191 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3192 HDA_AMP_MUTE, HDA_AMP_MUTE);
3193 snd_hda_codec_update_cache(codec, nid, 0,
3194 AC_VERB_SET_PIN_WIDGET_CONTROL,
3195 spec->multi_io[idx].ctl_in);
3196 }
3197 return 0;
3198}
3199
3200static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3201 struct snd_ctl_elem_value *ucontrol)
3202{
3203 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3204 struct alc_spec *spec = codec->spec;
3205 int i, ch;
3206
3207 ch = ucontrol->value.enumerated.item[0];
3208 if (ch < 0 || ch > spec->multi_ios)
3209 return -EINVAL;
3210 if (ch == (spec->ext_channel_count - 1) / 2)
3211 return 0;
3212 spec->ext_channel_count = (ch + 1) * 2;
3213 for (i = 0; i < spec->multi_ios; i++)
3214 alc_set_multi_io(codec, i, i < ch);
3215 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003216 if (spec->need_dac_fix && !spec->const_channel_count)
3217 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003218 return 1;
3219}
3220
Takashi Iwaia9111322011-05-02 11:30:18 +02003221static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003222 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3223 .name = "Channel Mode",
3224 .info = alc_auto_ch_mode_info,
3225 .get = alc_auto_ch_mode_get,
3226 .put = alc_auto_ch_mode_put,
3227};
3228
Takashi Iwaicb053a82011-06-27 11:32:07 +02003229static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
3230 int (*fill_dac)(struct hda_codec *))
Takashi Iwaice764ab2011-04-27 16:35:23 +02003231{
3232 struct alc_spec *spec = codec->spec;
3233 struct auto_pin_cfg *cfg = &spec->autocfg;
3234 unsigned int location, defcfg;
3235 int num_pins;
3236
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003237 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3238 /* use HP as primary out */
3239 cfg->speaker_outs = cfg->line_outs;
3240 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3241 sizeof(cfg->speaker_pins));
3242 cfg->line_outs = cfg->hp_outs;
3243 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3244 cfg->hp_outs = 0;
3245 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3246 cfg->line_out_type = AUTO_PIN_HP_OUT;
Takashi Iwaicb053a82011-06-27 11:32:07 +02003247 if (fill_dac)
3248 fill_dac(codec);
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003249 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003250 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003251 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003252 return 0;
3253
3254 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3255 location = get_defcfg_location(defcfg);
3256
3257 num_pins = alc_auto_fill_multi_ios(codec, location);
3258 if (num_pins > 0) {
3259 struct snd_kcontrol_new *knew;
3260
3261 knew = alc_kcontrol_new(spec);
3262 if (!knew)
3263 return -ENOMEM;
3264 *knew = alc_auto_channel_mode_enum;
3265 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3266 if (!knew->name)
3267 return -ENOMEM;
3268
3269 spec->multi_ios = num_pins;
3270 spec->ext_channel_count = 2;
3271 spec->multiout.num_dacs = num_pins + 1;
3272 }
3273 return 0;
3274}
3275
Takashi Iwai1d045db2011-07-07 18:23:21 +02003276/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3277 * active input pins
3278 */
3279static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3280{
3281 struct alc_spec *spec = codec->spec;
3282 const struct hda_input_mux *imux;
3283 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3284 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3285 int i, n, nums;
3286
3287 imux = spec->input_mux;
3288 if (!imux)
3289 return;
3290 if (spec->dyn_adc_switch)
3291 return;
3292
3293 nums = 0;
3294 for (n = 0; n < spec->num_adc_nids; n++) {
3295 hda_nid_t cap = spec->private_capsrc_nids[n];
3296 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3297 for (i = 0; i < imux->num_items; i++) {
3298 hda_nid_t pin = spec->imux_pins[i];
3299 if (pin) {
3300 if (get_connection_index(codec, cap, pin) < 0)
3301 break;
3302 } else if (num_conns <= imux->items[i].index)
3303 break;
3304 }
3305 if (i >= imux->num_items) {
3306 adc_nids[nums] = spec->private_adc_nids[n];
3307 capsrc_nids[nums++] = cap;
3308 }
3309 }
3310 if (!nums) {
3311 /* check whether ADC-switch is possible */
3312 if (!alc_check_dyn_adc_switch(codec)) {
3313 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3314 " using fallback 0x%x\n",
3315 codec->chip_name, spec->private_adc_nids[0]);
3316 spec->num_adc_nids = 1;
3317 spec->auto_mic = 0;
3318 return;
3319 }
3320 } else if (nums != spec->num_adc_nids) {
3321 memcpy(spec->private_adc_nids, adc_nids,
3322 nums * sizeof(hda_nid_t));
3323 memcpy(spec->private_capsrc_nids, capsrc_nids,
3324 nums * sizeof(hda_nid_t));
3325 spec->num_adc_nids = nums;
3326 }
3327
3328 if (spec->auto_mic)
3329 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3330 else if (spec->input_mux->num_items == 1)
3331 spec->num_adc_nids = 1; /* reduce to a single ADC */
3332}
3333
3334/*
3335 * initialize ADC paths
3336 */
3337static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3338{
3339 struct alc_spec *spec = codec->spec;
3340 hda_nid_t nid;
3341
3342 nid = spec->adc_nids[adc_idx];
3343 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003344 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003345 snd_hda_codec_write(codec, nid, 0,
3346 AC_VERB_SET_AMP_GAIN_MUTE,
3347 AMP_IN_MUTE(0));
3348 return;
3349 }
3350 if (!spec->capsrc_nids)
3351 return;
3352 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003353 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003354 snd_hda_codec_write(codec, nid, 0,
3355 AC_VERB_SET_AMP_GAIN_MUTE,
3356 AMP_OUT_MUTE);
3357}
3358
3359static void alc_auto_init_input_src(struct hda_codec *codec)
3360{
3361 struct alc_spec *spec = codec->spec;
3362 int c, nums;
3363
3364 for (c = 0; c < spec->num_adc_nids; c++)
3365 alc_auto_init_adc(codec, c);
3366 if (spec->dyn_adc_switch)
3367 nums = 1;
3368 else
3369 nums = spec->num_adc_nids;
3370 for (c = 0; c < nums; c++)
3371 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3372}
3373
3374/* add mic boosts if needed */
3375static int alc_auto_add_mic_boost(struct hda_codec *codec)
3376{
3377 struct alc_spec *spec = codec->spec;
3378 struct auto_pin_cfg *cfg = &spec->autocfg;
3379 int i, err;
3380 int type_idx = 0;
3381 hda_nid_t nid;
3382 const char *prev_label = NULL;
3383
3384 for (i = 0; i < cfg->num_inputs; i++) {
3385 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3386 break;
3387 nid = cfg->inputs[i].pin;
3388 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3389 const char *label;
3390 char boost_label[32];
3391
3392 label = hda_get_autocfg_input_label(codec, cfg, i);
3393 if (prev_label && !strcmp(label, prev_label))
3394 type_idx++;
3395 else
3396 type_idx = 0;
3397 prev_label = label;
3398
3399 snprintf(boost_label, sizeof(boost_label),
3400 "%s Boost Volume", label);
3401 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3402 boost_label, type_idx,
3403 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3404 if (err < 0)
3405 return err;
3406 }
3407 }
3408 return 0;
3409}
3410
3411/* select or unmute the given capsrc route */
3412static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3413 int idx)
3414{
3415 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3416 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3417 HDA_AMP_MUTE, 0);
3418 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3419 snd_hda_codec_write_cache(codec, cap, 0,
3420 AC_VERB_SET_CONNECT_SEL, idx);
3421 }
3422}
3423
3424/* set the default connection to that pin */
3425static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3426{
3427 struct alc_spec *spec = codec->spec;
3428 int i;
3429
3430 if (!pin)
3431 return 0;
3432 for (i = 0; i < spec->num_adc_nids; i++) {
3433 hda_nid_t cap = spec->capsrc_nids ?
3434 spec->capsrc_nids[i] : spec->adc_nids[i];
3435 int idx;
3436
3437 idx = get_connection_index(codec, cap, pin);
3438 if (idx < 0)
3439 continue;
3440 select_or_unmute_capsrc(codec, cap, idx);
3441 return i; /* return the found index */
3442 }
3443 return -1; /* not found */
3444}
3445
3446/* initialize some special cases for input sources */
3447static void alc_init_special_input_src(struct hda_codec *codec)
3448{
3449 struct alc_spec *spec = codec->spec;
3450 int i;
3451
3452 for (i = 0; i < spec->autocfg.num_inputs; i++)
3453 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3454}
3455
3456/* assign appropriate capture mixers */
3457static void set_capture_mixer(struct hda_codec *codec)
3458{
3459 struct alc_spec *spec = codec->spec;
3460 static const struct snd_kcontrol_new *caps[2][3] = {
3461 { alc_capture_mixer_nosrc1,
3462 alc_capture_mixer_nosrc2,
3463 alc_capture_mixer_nosrc3 },
3464 { alc_capture_mixer1,
3465 alc_capture_mixer2,
3466 alc_capture_mixer3 },
3467 };
3468
3469 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003470 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003471 if (!spec->capsrc_nids)
3472 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003473 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003474 return; /* no volume in capsrc, too */
3475 spec->vol_in_capsrc = 1;
3476 }
3477
3478 if (spec->num_adc_nids > 0) {
3479 int mux = 0;
3480 int num_adcs = 0;
3481
3482 if (spec->input_mux && spec->input_mux->num_items > 1)
3483 mux = 1;
3484 if (spec->auto_mic) {
3485 num_adcs = 1;
3486 mux = 0;
3487 } else if (spec->dyn_adc_switch)
3488 num_adcs = 1;
3489 if (!num_adcs) {
3490 if (spec->num_adc_nids > 3)
3491 spec->num_adc_nids = 3;
3492 else if (!spec->num_adc_nids)
3493 return;
3494 num_adcs = spec->num_adc_nids;
3495 }
3496 spec->cap_mixer = caps[mux][num_adcs - 1];
3497 }
3498}
3499
3500/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003501 * standard auto-parser initializations
3502 */
3503static void alc_auto_init_std(struct hda_codec *codec)
3504{
3505 struct alc_spec *spec = codec->spec;
3506 alc_auto_init_multi_out(codec);
3507 alc_auto_init_extra_out(codec);
3508 alc_auto_init_analog_input(codec);
3509 alc_auto_init_input_src(codec);
3510 alc_auto_init_digital(codec);
3511 if (spec->unsol_event)
3512 alc_inithook(codec);
3513}
3514
3515/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003516 * Digital-beep handlers
3517 */
3518#ifdef CONFIG_SND_HDA_INPUT_BEEP
3519#define set_beep_amp(spec, nid, idx, dir) \
3520 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3521
3522static const struct snd_pci_quirk beep_white_list[] = {
3523 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3524 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3525 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3526 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3527 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3528 {}
3529};
3530
3531static inline int has_cdefine_beep(struct hda_codec *codec)
3532{
3533 struct alc_spec *spec = codec->spec;
3534 const struct snd_pci_quirk *q;
3535 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3536 if (q)
3537 return q->value;
3538 return spec->cdefine.enable_pcbeep;
3539}
3540#else
3541#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3542#define has_cdefine_beep(codec) 0
3543#endif
3544
3545/* parse the BIOS configuration and set up the alc_spec */
3546/* return 1 if successful, 0 if the proper config is not found,
3547 * or a negative error code
3548 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003549static int alc_parse_auto_config(struct hda_codec *codec,
3550 const hda_nid_t *ignore_nids,
3551 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003552{
3553 struct alc_spec *spec = codec->spec;
3554 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003555
3556 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003557 ignore_nids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003558 if (err < 0)
3559 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003560 if (!spec->autocfg.line_outs) {
3561 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
3562 spec->multiout.max_channels = 2;
3563 spec->no_analog = 1;
3564 goto dig_only;
3565 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003566 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003567 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003568 err = alc_auto_fill_dac_nids(codec);
3569 if (err < 0)
3570 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003571 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
3572 if (err < 0)
3573 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003574 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
3575 if (err < 0)
3576 return err;
3577 err = alc_auto_create_hp_out(codec);
3578 if (err < 0)
3579 return err;
3580 err = alc_auto_create_speaker_out(codec);
3581 if (err < 0)
3582 return err;
3583 err = alc_auto_create_input_ctls(codec);
3584 if (err < 0)
3585 return err;
3586
3587 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3588
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003589 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02003590 alc_auto_parse_digital(codec);
3591
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003592 if (!spec->no_analog)
3593 alc_remove_invalid_adc_nids(codec);
3594
3595 if (ssid_nids)
3596 alc_ssid_check(codec, ssid_nids);
3597
3598 if (!spec->no_analog) {
3599 alc_auto_check_switches(codec);
3600 err = alc_auto_add_mic_boost(codec);
3601 if (err < 0)
3602 return err;
3603 }
3604
Takashi Iwai1d045db2011-07-07 18:23:21 +02003605 if (spec->kctls.list)
3606 add_mixer(spec, spec->kctls.list);
3607
Takashi Iwai1d045db2011-07-07 18:23:21 +02003608 return 1;
3609}
3610
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003611static int alc880_parse_auto_config(struct hda_codec *codec)
3612{
3613 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3614 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3615 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
3616}
3617
Takashi Iwai1d045db2011-07-07 18:23:21 +02003618#ifdef CONFIG_SND_HDA_POWER_SAVE
3619static const struct hda_amp_list alc880_loopbacks[] = {
3620 { 0x0b, HDA_INPUT, 0 },
3621 { 0x0b, HDA_INPUT, 1 },
3622 { 0x0b, HDA_INPUT, 2 },
3623 { 0x0b, HDA_INPUT, 3 },
3624 { 0x0b, HDA_INPUT, 4 },
3625 { } /* end */
3626};
3627#endif
3628
3629/*
3630 * board setups
3631 */
3632#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3633#define alc_board_config \
3634 snd_hda_check_board_config
3635#define alc_board_codec_sid_config \
3636 snd_hda_check_board_codec_sid_config
3637#include "alc_quirks.c"
3638#else
3639#define alc_board_config(codec, nums, models, tbl) -1
3640#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3641#define setup_preset(codec, x) /* NOP */
3642#endif
3643
3644/*
3645 * OK, here we have finally the patch for ALC880
3646 */
3647#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3648#include "alc880_quirks.c"
3649#endif
3650
3651static int patch_alc880(struct hda_codec *codec)
3652{
3653 struct alc_spec *spec;
3654 int board_config;
3655 int err;
3656
3657 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3658 if (spec == NULL)
3659 return -ENOMEM;
3660
3661 codec->spec = spec;
3662
3663 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003664 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003665
3666 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3667 alc880_models, alc880_cfg_tbl);
3668 if (board_config < 0) {
3669 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3670 codec->chip_name);
3671 board_config = ALC_MODEL_AUTO;
3672 }
3673
3674 if (board_config == ALC_MODEL_AUTO) {
3675 /* automatic parse from the BIOS config */
3676 err = alc880_parse_auto_config(codec);
3677 if (err < 0) {
3678 alc_free(codec);
3679 return err;
3680 }
3681#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3682 else if (!err) {
3683 printk(KERN_INFO
3684 "hda_codec: Cannot set up configuration "
3685 "from BIOS. Using 3-stack mode...\n");
3686 board_config = ALC880_3ST;
3687 }
3688#endif
3689 }
3690
Takashi Iwai1d045db2011-07-07 18:23:21 +02003691 if (board_config != ALC_MODEL_AUTO)
3692 setup_preset(codec, &alc880_presets[board_config]);
3693
Takashi Iwai60a6a842011-07-27 14:01:24 +02003694 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003695 alc_auto_fill_adc_caps(codec);
3696 alc_rebuild_imux_for_auto_mic(codec);
3697 alc_remove_invalid_adc_nids(codec);
3698 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003699
3700 if (!spec->no_analog && !spec->cap_mixer)
3701 set_capture_mixer(codec);
3702
3703 if (!spec->no_analog) {
3704 err = snd_hda_attach_beep_device(codec, 0x1);
3705 if (err < 0) {
3706 alc_free(codec);
3707 return err;
3708 }
3709 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3710 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003711
3712 spec->vmaster_nid = 0x0c;
3713
3714 codec->patch_ops = alc_patch_ops;
3715 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003716 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003717#ifdef CONFIG_SND_HDA_POWER_SAVE
3718 if (!spec->loopback.amplist)
3719 spec->loopback.amplist = alc880_loopbacks;
3720#endif
3721
3722 return 0;
3723}
3724
3725
3726/*
3727 * ALC260 support
3728 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003729static int alc260_parse_auto_config(struct hda_codec *codec)
3730{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003731 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003732 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
3733 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003734}
3735
Takashi Iwai1d045db2011-07-07 18:23:21 +02003736#ifdef CONFIG_SND_HDA_POWER_SAVE
3737static const struct hda_amp_list alc260_loopbacks[] = {
3738 { 0x07, HDA_INPUT, 0 },
3739 { 0x07, HDA_INPUT, 1 },
3740 { 0x07, HDA_INPUT, 2 },
3741 { 0x07, HDA_INPUT, 3 },
3742 { 0x07, HDA_INPUT, 4 },
3743 { } /* end */
3744};
3745#endif
3746
3747/*
3748 * Pin config fixes
3749 */
3750enum {
3751 PINFIX_HP_DC5750,
3752};
3753
3754static const struct alc_fixup alc260_fixups[] = {
3755 [PINFIX_HP_DC5750] = {
3756 .type = ALC_FIXUP_PINS,
3757 .v.pins = (const struct alc_pincfg[]) {
3758 { 0x11, 0x90130110 }, /* speaker */
3759 { }
3760 }
3761 },
3762};
3763
3764static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3765 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3766 {}
3767};
3768
3769/*
3770 */
3771#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3772#include "alc260_quirks.c"
3773#endif
3774
3775static int patch_alc260(struct hda_codec *codec)
3776{
3777 struct alc_spec *spec;
3778 int err, board_config;
3779
3780 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3781 if (spec == NULL)
3782 return -ENOMEM;
3783
3784 codec->spec = spec;
3785
3786 spec->mixer_nid = 0x07;
3787
3788 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3789 alc260_models, alc260_cfg_tbl);
3790 if (board_config < 0) {
3791 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3792 codec->chip_name);
3793 board_config = ALC_MODEL_AUTO;
3794 }
3795
3796 if (board_config == ALC_MODEL_AUTO) {
3797 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3798 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3799 }
3800
3801 if (board_config == ALC_MODEL_AUTO) {
3802 /* automatic parse from the BIOS config */
3803 err = alc260_parse_auto_config(codec);
3804 if (err < 0) {
3805 alc_free(codec);
3806 return err;
3807 }
3808#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3809 else if (!err) {
3810 printk(KERN_INFO
3811 "hda_codec: Cannot set up configuration "
3812 "from BIOS. Using base mode...\n");
3813 board_config = ALC260_BASIC;
3814 }
3815#endif
3816 }
3817
Takashi Iwai1d045db2011-07-07 18:23:21 +02003818 if (board_config != ALC_MODEL_AUTO)
3819 setup_preset(codec, &alc260_presets[board_config]);
3820
Takashi Iwai60a6a842011-07-27 14:01:24 +02003821 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003822 alc_auto_fill_adc_caps(codec);
3823 alc_rebuild_imux_for_auto_mic(codec);
3824 alc_remove_invalid_adc_nids(codec);
3825 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003826
3827 if (!spec->no_analog && !spec->cap_mixer)
3828 set_capture_mixer(codec);
3829
3830 if (!spec->no_analog) {
3831 err = snd_hda_attach_beep_device(codec, 0x1);
3832 if (err < 0) {
3833 alc_free(codec);
3834 return err;
3835 }
3836 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3837 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003838
3839 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3840
3841 spec->vmaster_nid = 0x08;
3842
3843 codec->patch_ops = alc_patch_ops;
3844 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02003845 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003846 spec->shutup = alc_eapd_shutup;
3847#ifdef CONFIG_SND_HDA_POWER_SAVE
3848 if (!spec->loopback.amplist)
3849 spec->loopback.amplist = alc260_loopbacks;
3850#endif
3851
3852 return 0;
3853}
3854
3855
3856/*
3857 * ALC882/883/885/888/889 support
3858 *
3859 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3860 * configuration. Each pin widget can choose any input DACs and a mixer.
3861 * Each ADC is connected from a mixer of all inputs. This makes possible
3862 * 6-channel independent captures.
3863 *
3864 * In addition, an independent DAC for the multi-playback (not used in this
3865 * driver yet).
3866 */
3867#ifdef CONFIG_SND_HDA_POWER_SAVE
3868#define alc882_loopbacks alc880_loopbacks
3869#endif
3870
3871/*
3872 * Pin config fixes
3873 */
3874enum {
3875 PINFIX_ABIT_AW9D_MAX,
3876 PINFIX_LENOVO_Y530,
3877 PINFIX_PB_M5210,
3878 PINFIX_ACER_ASPIRE_7736,
3879};
3880
3881static const struct alc_fixup alc882_fixups[] = {
3882 [PINFIX_ABIT_AW9D_MAX] = {
3883 .type = ALC_FIXUP_PINS,
3884 .v.pins = (const struct alc_pincfg[]) {
3885 { 0x15, 0x01080104 }, /* side */
3886 { 0x16, 0x01011012 }, /* rear */
3887 { 0x17, 0x01016011 }, /* clfe */
3888 { }
3889 }
3890 },
3891 [PINFIX_LENOVO_Y530] = {
3892 .type = ALC_FIXUP_PINS,
3893 .v.pins = (const struct alc_pincfg[]) {
3894 { 0x15, 0x99130112 }, /* rear int speakers */
3895 { 0x16, 0x99130111 }, /* subwoofer */
3896 { }
3897 }
3898 },
3899 [PINFIX_PB_M5210] = {
3900 .type = ALC_FIXUP_VERBS,
3901 .v.verbs = (const struct hda_verb[]) {
3902 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
3903 {}
3904 }
3905 },
3906 [PINFIX_ACER_ASPIRE_7736] = {
3907 .type = ALC_FIXUP_SKU,
3908 .v.sku = ALC_FIXUP_SKU_IGNORE,
3909 },
3910};
3911
3912static const struct snd_pci_quirk alc882_fixup_tbl[] = {
3913 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
3914 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
3915 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
3916 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
3917 {}
3918};
3919
3920/*
3921 * BIOS auto configuration
3922 */
3923/* almost identical with ALC880 parser... */
3924static int alc882_parse_auto_config(struct hda_codec *codec)
3925{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003926 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003927 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3928 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003929}
3930
Takashi Iwai1d045db2011-07-07 18:23:21 +02003931/*
3932 */
3933#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3934#include "alc882_quirks.c"
3935#endif
3936
3937static int patch_alc882(struct hda_codec *codec)
3938{
3939 struct alc_spec *spec;
3940 int err, board_config;
3941
3942 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3943 if (spec == NULL)
3944 return -ENOMEM;
3945
3946 codec->spec = spec;
3947
3948 spec->mixer_nid = 0x0b;
3949
3950 switch (codec->vendor_id) {
3951 case 0x10ec0882:
3952 case 0x10ec0885:
3953 break;
3954 default:
3955 /* ALC883 and variants */
3956 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
3957 break;
3958 }
3959
3960 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
3961 alc882_models, alc882_cfg_tbl);
3962
3963 if (board_config < 0)
3964 board_config = alc_board_codec_sid_config(codec,
3965 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
3966
3967 if (board_config < 0) {
3968 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3969 codec->chip_name);
3970 board_config = ALC_MODEL_AUTO;
3971 }
3972
3973 if (board_config == ALC_MODEL_AUTO) {
3974 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
3975 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3976 }
3977
3978 alc_auto_parse_customize_define(codec);
3979
3980 if (board_config == ALC_MODEL_AUTO) {
3981 /* automatic parse from the BIOS config */
3982 err = alc882_parse_auto_config(codec);
3983 if (err < 0) {
3984 alc_free(codec);
3985 return err;
3986 }
3987#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3988 else if (!err) {
3989 printk(KERN_INFO
3990 "hda_codec: Cannot set up configuration "
3991 "from BIOS. Using base mode...\n");
3992 board_config = ALC882_3ST_DIG;
3993 }
3994#endif
3995 }
3996
Takashi Iwai1d045db2011-07-07 18:23:21 +02003997 if (board_config != ALC_MODEL_AUTO)
3998 setup_preset(codec, &alc882_presets[board_config]);
3999
Takashi Iwai60a6a842011-07-27 14:01:24 +02004000 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004001 alc_auto_fill_adc_caps(codec);
4002 alc_rebuild_imux_for_auto_mic(codec);
4003 alc_remove_invalid_adc_nids(codec);
4004 }
4005
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004006 if (!spec->no_analog && !spec->cap_mixer)
4007 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004008
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004009 if (!spec->no_analog && has_cdefine_beep(codec)) {
4010 err = snd_hda_attach_beep_device(codec, 0x1);
4011 if (err < 0) {
4012 alc_free(codec);
4013 return err;
4014 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004015 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004016 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004017
4018 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4019
4020 spec->vmaster_nid = 0x0c;
4021
4022 codec->patch_ops = alc_patch_ops;
4023 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004024 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004025
4026 alc_init_jacks(codec);
4027#ifdef CONFIG_SND_HDA_POWER_SAVE
4028 if (!spec->loopback.amplist)
4029 spec->loopback.amplist = alc882_loopbacks;
4030#endif
4031
4032 return 0;
4033}
4034
4035
4036/*
4037 * ALC262 support
4038 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004039static int alc262_parse_auto_config(struct hda_codec *codec)
4040{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004041 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004042 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4043 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004044}
4045
4046/*
4047 * Pin config fixes
4048 */
4049enum {
4050 PINFIX_FSC_H270,
4051 PINFIX_HP_Z200,
4052};
4053
4054static const struct alc_fixup alc262_fixups[] = {
4055 [PINFIX_FSC_H270] = {
4056 .type = ALC_FIXUP_PINS,
4057 .v.pins = (const struct alc_pincfg[]) {
4058 { 0x14, 0x99130110 }, /* speaker */
4059 { 0x15, 0x0221142f }, /* front HP */
4060 { 0x1b, 0x0121141f }, /* rear HP */
4061 { }
4062 }
4063 },
4064 [PINFIX_HP_Z200] = {
4065 .type = ALC_FIXUP_PINS,
4066 .v.pins = (const struct alc_pincfg[]) {
4067 { 0x16, 0x99130120 }, /* internal speaker */
4068 { }
4069 }
4070 },
4071};
4072
4073static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4074 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4075 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4076 {}
4077};
4078
4079
4080#ifdef CONFIG_SND_HDA_POWER_SAVE
4081#define alc262_loopbacks alc880_loopbacks
4082#endif
4083
Takashi Iwai1d045db2011-07-07 18:23:21 +02004084/*
4085 */
4086#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4087#include "alc262_quirks.c"
4088#endif
4089
4090static int patch_alc262(struct hda_codec *codec)
4091{
4092 struct alc_spec *spec;
4093 int board_config;
4094 int err;
4095
4096 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4097 if (spec == NULL)
4098 return -ENOMEM;
4099
4100 codec->spec = spec;
4101
4102 spec->mixer_nid = 0x0b;
4103
4104#if 0
4105 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4106 * under-run
4107 */
4108 {
4109 int tmp;
4110 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4111 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4112 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4113 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4114 }
4115#endif
4116 alc_auto_parse_customize_define(codec);
4117
4118 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4119
4120 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4121 alc262_models, alc262_cfg_tbl);
4122
4123 if (board_config < 0) {
4124 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4125 codec->chip_name);
4126 board_config = ALC_MODEL_AUTO;
4127 }
4128
4129 if (board_config == ALC_MODEL_AUTO) {
4130 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4131 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4132 }
4133
4134 if (board_config == ALC_MODEL_AUTO) {
4135 /* automatic parse from the BIOS config */
4136 err = alc262_parse_auto_config(codec);
4137 if (err < 0) {
4138 alc_free(codec);
4139 return err;
4140 }
4141#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4142 else if (!err) {
4143 printk(KERN_INFO
4144 "hda_codec: Cannot set up configuration "
4145 "from BIOS. Using base mode...\n");
4146 board_config = ALC262_BASIC;
4147 }
4148#endif
4149 }
4150
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004151 if (board_config != ALC_MODEL_AUTO)
4152 setup_preset(codec, &alc262_presets[board_config]);
4153
Takashi Iwai60a6a842011-07-27 14:01:24 +02004154 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004155 alc_auto_fill_adc_caps(codec);
4156 alc_rebuild_imux_for_auto_mic(codec);
4157 alc_remove_invalid_adc_nids(codec);
4158 }
4159
4160 if (!spec->no_analog && !spec->cap_mixer)
4161 set_capture_mixer(codec);
4162
Takashi Iwai1d045db2011-07-07 18:23:21 +02004163 if (!spec->no_analog && has_cdefine_beep(codec)) {
4164 err = snd_hda_attach_beep_device(codec, 0x1);
4165 if (err < 0) {
4166 alc_free(codec);
4167 return err;
4168 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004169 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004170 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004171
4172 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4173
4174 spec->vmaster_nid = 0x0c;
4175
4176 codec->patch_ops = alc_patch_ops;
4177 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004178 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004179 spec->shutup = alc_eapd_shutup;
4180
4181 alc_init_jacks(codec);
4182#ifdef CONFIG_SND_HDA_POWER_SAVE
4183 if (!spec->loopback.amplist)
4184 spec->loopback.amplist = alc262_loopbacks;
4185#endif
4186
4187 return 0;
4188}
4189
4190/*
4191 * ALC268
4192 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004193/* bind Beep switches of both NID 0x0f and 0x10 */
4194static const struct hda_bind_ctls alc268_bind_beep_sw = {
4195 .ops = &snd_hda_bind_sw,
4196 .values = {
4197 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4198 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4199 0
4200 },
4201};
4202
4203static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4204 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4205 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4206 { }
4207};
4208
4209/* set PCBEEP vol = 0, mute connections */
4210static const struct hda_verb alc268_beep_init_verbs[] = {
4211 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4212 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4213 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4214 { }
4215};
4216
4217/*
4218 * BIOS auto configuration
4219 */
4220static int alc268_parse_auto_config(struct hda_codec *codec)
4221{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004222 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004223 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004224 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4225 if (err > 0) {
4226 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4227 add_mixer(spec, alc268_beep_mixer);
4228 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004229 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004230 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004231 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004232}
4233
Takashi Iwai1d045db2011-07-07 18:23:21 +02004234/*
4235 */
4236#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4237#include "alc268_quirks.c"
4238#endif
4239
4240static int patch_alc268(struct hda_codec *codec)
4241{
4242 struct alc_spec *spec;
4243 int board_config;
4244 int i, has_beep, err;
4245
4246 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4247 if (spec == NULL)
4248 return -ENOMEM;
4249
4250 codec->spec = spec;
4251
4252 /* ALC268 has no aa-loopback mixer */
4253
4254 board_config = alc_board_config(codec, ALC268_MODEL_LAST,
4255 alc268_models, alc268_cfg_tbl);
4256
4257 if (board_config < 0)
4258 board_config = alc_board_codec_sid_config(codec,
4259 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
4260
4261 if (board_config < 0) {
4262 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4263 codec->chip_name);
4264 board_config = ALC_MODEL_AUTO;
4265 }
4266
4267 if (board_config == ALC_MODEL_AUTO) {
4268 /* automatic parse from the BIOS config */
4269 err = alc268_parse_auto_config(codec);
4270 if (err < 0) {
4271 alc_free(codec);
4272 return err;
4273 }
4274#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4275 else if (!err) {
4276 printk(KERN_INFO
4277 "hda_codec: Cannot set up configuration "
4278 "from BIOS. Using base mode...\n");
4279 board_config = ALC268_3ST;
4280 }
4281#endif
4282 }
4283
4284 if (board_config != ALC_MODEL_AUTO)
4285 setup_preset(codec, &alc268_presets[board_config]);
4286
4287 has_beep = 0;
4288 for (i = 0; i < spec->num_mixers; i++) {
4289 if (spec->mixers[i] == alc268_beep_mixer) {
4290 has_beep = 1;
4291 break;
4292 }
4293 }
4294
4295 if (has_beep) {
4296 err = snd_hda_attach_beep_device(codec, 0x1);
4297 if (err < 0) {
4298 alc_free(codec);
4299 return err;
4300 }
4301 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4302 /* override the amp caps for beep generator */
4303 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4304 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4305 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4306 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4307 (0 << AC_AMPCAP_MUTE_SHIFT));
4308 }
4309
Takashi Iwai60a6a842011-07-27 14:01:24 +02004310 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004311 alc_auto_fill_adc_caps(codec);
4312 alc_rebuild_imux_for_auto_mic(codec);
4313 alc_remove_invalid_adc_nids(codec);
4314 }
4315
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004316 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004317 set_capture_mixer(codec);
4318
4319 spec->vmaster_nid = 0x02;
4320
4321 codec->patch_ops = alc_patch_ops;
4322 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004323 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004324 spec->shutup = alc_eapd_shutup;
4325
4326 alc_init_jacks(codec);
4327
4328 return 0;
4329}
4330
4331/*
4332 * ALC269
4333 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004334#ifdef CONFIG_SND_HDA_POWER_SAVE
4335#define alc269_loopbacks alc880_loopbacks
4336#endif
4337
4338static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4339 .substreams = 1,
4340 .channels_min = 2,
4341 .channels_max = 8,
4342 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4343 /* NID is set in alc_build_pcms */
4344 .ops = {
4345 .open = alc_playback_pcm_open,
4346 .prepare = alc_playback_pcm_prepare,
4347 .cleanup = alc_playback_pcm_cleanup
4348 },
4349};
4350
4351static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4352 .substreams = 1,
4353 .channels_min = 2,
4354 .channels_max = 2,
4355 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4356 /* NID is set in alc_build_pcms */
4357};
4358
4359#ifdef CONFIG_SND_HDA_POWER_SAVE
4360static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4361{
4362 switch (codec->subsystem_id) {
4363 case 0x103c1586:
4364 return 1;
4365 }
4366 return 0;
4367}
4368
4369static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4370{
4371 /* update mute-LED according to the speaker mute state */
4372 if (nid == 0x01 || nid == 0x14) {
4373 int pinval;
4374 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4375 HDA_AMP_MUTE)
4376 pinval = 0x24;
4377 else
4378 pinval = 0x20;
4379 /* mic2 vref pin is used for mute LED control */
4380 snd_hda_codec_update_cache(codec, 0x19, 0,
4381 AC_VERB_SET_PIN_WIDGET_CONTROL,
4382 pinval);
4383 }
4384 return alc_check_power_status(codec, nid);
4385}
4386#endif /* CONFIG_SND_HDA_POWER_SAVE */
4387
4388/* different alc269-variants */
4389enum {
4390 ALC269_TYPE_ALC269VA,
4391 ALC269_TYPE_ALC269VB,
4392 ALC269_TYPE_ALC269VC,
4393};
4394
4395/*
4396 * BIOS auto configuration
4397 */
4398static int alc269_parse_auto_config(struct hda_codec *codec)
4399{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004400 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004401 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
4402 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4403 struct alc_spec *spec = codec->spec;
4404 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
4405 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004406
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004407 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004408}
4409
Takashi Iwai1d045db2011-07-07 18:23:21 +02004410static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4411{
4412 int val = alc_read_coef_idx(codec, 0x04);
4413 if (power_up)
4414 val |= 1 << 11;
4415 else
4416 val &= ~(1 << 11);
4417 alc_write_coef_idx(codec, 0x04, val);
4418}
4419
4420static void alc269_shutup(struct hda_codec *codec)
4421{
4422 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4423 alc269_toggle_power_output(codec, 0);
4424 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4425 alc269_toggle_power_output(codec, 0);
4426 msleep(150);
4427 }
4428}
4429
Takashi Iwai2a439522011-07-26 09:52:50 +02004430#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004431static int alc269_resume(struct hda_codec *codec)
4432{
4433 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4434 alc269_toggle_power_output(codec, 0);
4435 msleep(150);
4436 }
4437
4438 codec->patch_ops.init(codec);
4439
4440 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4441 alc269_toggle_power_output(codec, 1);
4442 msleep(200);
4443 }
4444
4445 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4446 alc269_toggle_power_output(codec, 1);
4447
4448 snd_hda_codec_resume_amp(codec);
4449 snd_hda_codec_resume_cache(codec);
4450 hda_call_check_power_status(codec, 0x01);
4451 return 0;
4452}
Takashi Iwai2a439522011-07-26 09:52:50 +02004453#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004454
4455static void alc269_fixup_hweq(struct hda_codec *codec,
4456 const struct alc_fixup *fix, int action)
4457{
4458 int coef;
4459
4460 if (action != ALC_FIXUP_ACT_INIT)
4461 return;
4462 coef = alc_read_coef_idx(codec, 0x1e);
4463 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4464}
4465
4466static void alc271_fixup_dmic(struct hda_codec *codec,
4467 const struct alc_fixup *fix, int action)
4468{
4469 static const struct hda_verb verbs[] = {
4470 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4471 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4472 {}
4473 };
4474 unsigned int cfg;
4475
4476 if (strcmp(codec->chip_name, "ALC271X"))
4477 return;
4478 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4479 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4480 snd_hda_sequence_write(codec, verbs);
4481}
4482
Takashi Iwai017f2a12011-07-09 14:42:25 +02004483static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4484 const struct alc_fixup *fix, int action)
4485{
4486 struct alc_spec *spec = codec->spec;
4487
4488 if (action != ALC_FIXUP_ACT_PROBE)
4489 return;
4490
4491 /* Due to a hardware problem on Lenovo Ideadpad, we need to
4492 * fix the sample rate of analog I/O to 44.1kHz
4493 */
4494 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
4495 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4496}
4497
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004498static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4499 const struct alc_fixup *fix, int action)
4500{
4501 int coef;
4502
4503 if (action != ALC_FIXUP_ACT_INIT)
4504 return;
4505 /* The digital-mic unit sends PDM (differential signal) instead of
4506 * the standard PCM, thus you can't record a valid mono stream as is.
4507 * Below is a workaround specific to ALC269 to control the dmic
4508 * signal source as mono.
4509 */
4510 coef = alc_read_coef_idx(codec, 0x07);
4511 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4512}
4513
Takashi Iwai1d045db2011-07-07 18:23:21 +02004514enum {
4515 ALC269_FIXUP_SONY_VAIO,
4516 ALC275_FIXUP_SONY_VAIO_GPIO2,
4517 ALC269_FIXUP_DELL_M101Z,
4518 ALC269_FIXUP_SKU_IGNORE,
4519 ALC269_FIXUP_ASUS_G73JW,
4520 ALC269_FIXUP_LENOVO_EAPD,
4521 ALC275_FIXUP_SONY_HWEQ,
4522 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004523 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004524 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004525};
4526
4527static const struct alc_fixup alc269_fixups[] = {
4528 [ALC269_FIXUP_SONY_VAIO] = {
4529 .type = ALC_FIXUP_VERBS,
4530 .v.verbs = (const struct hda_verb[]) {
4531 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4532 {}
4533 }
4534 },
4535 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4536 .type = ALC_FIXUP_VERBS,
4537 .v.verbs = (const struct hda_verb[]) {
4538 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4539 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4540 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4541 { }
4542 },
4543 .chained = true,
4544 .chain_id = ALC269_FIXUP_SONY_VAIO
4545 },
4546 [ALC269_FIXUP_DELL_M101Z] = {
4547 .type = ALC_FIXUP_VERBS,
4548 .v.verbs = (const struct hda_verb[]) {
4549 /* Enables internal speaker */
4550 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4551 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4552 {}
4553 }
4554 },
4555 [ALC269_FIXUP_SKU_IGNORE] = {
4556 .type = ALC_FIXUP_SKU,
4557 .v.sku = ALC_FIXUP_SKU_IGNORE,
4558 },
4559 [ALC269_FIXUP_ASUS_G73JW] = {
4560 .type = ALC_FIXUP_PINS,
4561 .v.pins = (const struct alc_pincfg[]) {
4562 { 0x17, 0x99130111 }, /* subwoofer */
4563 { }
4564 }
4565 },
4566 [ALC269_FIXUP_LENOVO_EAPD] = {
4567 .type = ALC_FIXUP_VERBS,
4568 .v.verbs = (const struct hda_verb[]) {
4569 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4570 {}
4571 }
4572 },
4573 [ALC275_FIXUP_SONY_HWEQ] = {
4574 .type = ALC_FIXUP_FUNC,
4575 .v.func = alc269_fixup_hweq,
4576 .chained = true,
4577 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4578 },
4579 [ALC271_FIXUP_DMIC] = {
4580 .type = ALC_FIXUP_FUNC,
4581 .v.func = alc271_fixup_dmic,
4582 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004583 [ALC269_FIXUP_PCM_44K] = {
4584 .type = ALC_FIXUP_FUNC,
4585 .v.func = alc269_fixup_pcm_44k,
4586 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004587 [ALC269_FIXUP_STEREO_DMIC] = {
4588 .type = ALC_FIXUP_FUNC,
4589 .v.func = alc269_fixup_stereo_dmic,
4590 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004591};
4592
4593static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02004594 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004595 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4596 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4597 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4598 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4599 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004600 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4601 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4602 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4603 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4604 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4605 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
4606 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4607 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4608 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4609 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4610 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02004611 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004612 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
4613 {}
4614};
4615
4616
4617static int alc269_fill_coef(struct hda_codec *codec)
4618{
4619 int val;
4620
4621 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4622 alc_write_coef_idx(codec, 0xf, 0x960b);
4623 alc_write_coef_idx(codec, 0xe, 0x8817);
4624 }
4625
4626 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4627 alc_write_coef_idx(codec, 0xf, 0x960b);
4628 alc_write_coef_idx(codec, 0xe, 0x8814);
4629 }
4630
4631 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4632 val = alc_read_coef_idx(codec, 0x04);
4633 /* Power up output pin */
4634 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4635 }
4636
4637 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4638 val = alc_read_coef_idx(codec, 0xd);
4639 if ((val & 0x0c00) >> 10 != 0x1) {
4640 /* Capless ramp up clock control */
4641 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4642 }
4643 val = alc_read_coef_idx(codec, 0x17);
4644 if ((val & 0x01c0) >> 6 != 0x4) {
4645 /* Class D power on reset */
4646 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4647 }
4648 }
4649
4650 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4651 alc_write_coef_idx(codec, 0xd, val | (1<<14));
4652
4653 val = alc_read_coef_idx(codec, 0x4); /* HP */
4654 alc_write_coef_idx(codec, 0x4, val | (1<<11));
4655
4656 return 0;
4657}
4658
4659/*
4660 */
4661#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4662#include "alc269_quirks.c"
4663#endif
4664
4665static int patch_alc269(struct hda_codec *codec)
4666{
4667 struct alc_spec *spec;
4668 int board_config, coef;
4669 int err;
4670
4671 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4672 if (spec == NULL)
4673 return -ENOMEM;
4674
4675 codec->spec = spec;
4676
4677 spec->mixer_nid = 0x0b;
4678
4679 alc_auto_parse_customize_define(codec);
4680
4681 if (codec->vendor_id == 0x10ec0269) {
4682 spec->codec_variant = ALC269_TYPE_ALC269VA;
4683 coef = alc_read_coef_idx(codec, 0);
4684 if ((coef & 0x00f0) == 0x0010) {
4685 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
4686 spec->cdefine.platform_type == 1) {
4687 alc_codec_rename(codec, "ALC271X");
4688 } else if ((coef & 0xf000) == 0x2000) {
4689 alc_codec_rename(codec, "ALC259");
4690 } else if ((coef & 0xf000) == 0x3000) {
4691 alc_codec_rename(codec, "ALC258");
4692 } else if ((coef & 0xfff0) == 0x3010) {
4693 alc_codec_rename(codec, "ALC277");
4694 } else {
4695 alc_codec_rename(codec, "ALC269VB");
4696 }
4697 spec->codec_variant = ALC269_TYPE_ALC269VB;
4698 } else if ((coef & 0x00f0) == 0x0020) {
4699 if (coef == 0xa023)
4700 alc_codec_rename(codec, "ALC259");
4701 else if (coef == 0x6023)
4702 alc_codec_rename(codec, "ALC281X");
4703 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4704 codec->bus->pci->subsystem_device == 0x21f3)
4705 alc_codec_rename(codec, "ALC3202");
4706 else
4707 alc_codec_rename(codec, "ALC269VC");
4708 spec->codec_variant = ALC269_TYPE_ALC269VC;
4709 } else
4710 alc_fix_pll_init(codec, 0x20, 0x04, 15);
4711 alc269_fill_coef(codec);
4712 }
4713
4714 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
4715 alc269_models, alc269_cfg_tbl);
4716
4717 if (board_config < 0) {
4718 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4719 codec->chip_name);
4720 board_config = ALC_MODEL_AUTO;
4721 }
4722
4723 if (board_config == ALC_MODEL_AUTO) {
4724 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
4725 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4726 }
4727
4728 if (board_config == ALC_MODEL_AUTO) {
4729 /* automatic parse from the BIOS config */
4730 err = alc269_parse_auto_config(codec);
4731 if (err < 0) {
4732 alc_free(codec);
4733 return err;
4734 }
4735#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4736 else if (!err) {
4737 printk(KERN_INFO
4738 "hda_codec: Cannot set up configuration "
4739 "from BIOS. Using base mode...\n");
4740 board_config = ALC269_BASIC;
4741 }
4742#endif
4743 }
4744
Takashi Iwai1d045db2011-07-07 18:23:21 +02004745 if (board_config != ALC_MODEL_AUTO)
4746 setup_preset(codec, &alc269_presets[board_config]);
4747
Takashi Iwai60a6a842011-07-27 14:01:24 +02004748 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004749 alc_auto_fill_adc_caps(codec);
4750 alc_rebuild_imux_for_auto_mic(codec);
4751 alc_remove_invalid_adc_nids(codec);
4752 }
4753
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004754 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004755 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004756
4757 if (!spec->no_analog && has_cdefine_beep(codec)) {
4758 err = snd_hda_attach_beep_device(codec, 0x1);
4759 if (err < 0) {
4760 alc_free(codec);
4761 return err;
4762 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004763 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004764 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004765
4766 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4767
4768 spec->vmaster_nid = 0x02;
4769
4770 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02004771#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004772 codec->patch_ops.resume = alc269_resume;
4773#endif
4774 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004775 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004776 spec->shutup = alc269_shutup;
4777
4778 alc_init_jacks(codec);
4779#ifdef CONFIG_SND_HDA_POWER_SAVE
4780 if (!spec->loopback.amplist)
4781 spec->loopback.amplist = alc269_loopbacks;
4782 if (alc269_mic2_for_mute_led(codec))
4783 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
4784#endif
4785
4786 return 0;
4787}
4788
4789/*
4790 * ALC861
4791 */
4792
Takashi Iwai1d045db2011-07-07 18:23:21 +02004793static int alc861_parse_auto_config(struct hda_codec *codec)
4794{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004795 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004796 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4797 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004798}
4799
Takashi Iwai1d045db2011-07-07 18:23:21 +02004800#ifdef CONFIG_SND_HDA_POWER_SAVE
4801static const struct hda_amp_list alc861_loopbacks[] = {
4802 { 0x15, HDA_INPUT, 0 },
4803 { 0x15, HDA_INPUT, 1 },
4804 { 0x15, HDA_INPUT, 2 },
4805 { 0x15, HDA_INPUT, 3 },
4806 { } /* end */
4807};
4808#endif
4809
4810
4811/* Pin config fixes */
4812enum {
4813 PINFIX_FSC_AMILO_PI1505,
4814};
4815
4816static const struct alc_fixup alc861_fixups[] = {
4817 [PINFIX_FSC_AMILO_PI1505] = {
4818 .type = ALC_FIXUP_PINS,
4819 .v.pins = (const struct alc_pincfg[]) {
4820 { 0x0b, 0x0221101f }, /* HP */
4821 { 0x0f, 0x90170310 }, /* speaker */
4822 { }
4823 }
4824 },
4825};
4826
4827static const struct snd_pci_quirk alc861_fixup_tbl[] = {
4828 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
4829 {}
4830};
4831
4832/*
4833 */
4834#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4835#include "alc861_quirks.c"
4836#endif
4837
4838static int patch_alc861(struct hda_codec *codec)
4839{
4840 struct alc_spec *spec;
4841 int board_config;
4842 int err;
4843
4844 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4845 if (spec == NULL)
4846 return -ENOMEM;
4847
4848 codec->spec = spec;
4849
4850 spec->mixer_nid = 0x15;
4851
4852 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
4853 alc861_models, alc861_cfg_tbl);
4854
4855 if (board_config < 0) {
4856 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4857 codec->chip_name);
4858 board_config = ALC_MODEL_AUTO;
4859 }
4860
4861 if (board_config == ALC_MODEL_AUTO) {
4862 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
4863 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4864 }
4865
4866 if (board_config == ALC_MODEL_AUTO) {
4867 /* automatic parse from the BIOS config */
4868 err = alc861_parse_auto_config(codec);
4869 if (err < 0) {
4870 alc_free(codec);
4871 return err;
4872 }
4873#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4874 else if (!err) {
4875 printk(KERN_INFO
4876 "hda_codec: Cannot set up configuration "
4877 "from BIOS. Using base mode...\n");
4878 board_config = ALC861_3ST_DIG;
4879 }
4880#endif
4881 }
4882
Takashi Iwai1d045db2011-07-07 18:23:21 +02004883 if (board_config != ALC_MODEL_AUTO)
4884 setup_preset(codec, &alc861_presets[board_config]);
4885
Takashi Iwai60a6a842011-07-27 14:01:24 +02004886 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004887 alc_auto_fill_adc_caps(codec);
4888 alc_rebuild_imux_for_auto_mic(codec);
4889 alc_remove_invalid_adc_nids(codec);
4890 }
4891
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004892 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004893 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004894
4895 if (!spec->no_analog) {
4896 err = snd_hda_attach_beep_device(codec, 0x23);
4897 if (err < 0) {
4898 alc_free(codec);
4899 return err;
4900 }
4901 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
4902 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004903
4904 spec->vmaster_nid = 0x03;
4905
4906 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4907
4908 codec->patch_ops = alc_patch_ops;
4909 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02004910 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004911#ifdef CONFIG_SND_HDA_POWER_SAVE
4912 spec->power_hook = alc_power_eapd;
4913#endif
4914 }
4915#ifdef CONFIG_SND_HDA_POWER_SAVE
4916 if (!spec->loopback.amplist)
4917 spec->loopback.amplist = alc861_loopbacks;
4918#endif
4919
4920 return 0;
4921}
4922
4923/*
4924 * ALC861-VD support
4925 *
4926 * Based on ALC882
4927 *
4928 * In addition, an independent DAC
4929 */
4930#ifdef CONFIG_SND_HDA_POWER_SAVE
4931#define alc861vd_loopbacks alc880_loopbacks
4932#endif
4933
Takashi Iwai1d045db2011-07-07 18:23:21 +02004934static int alc861vd_parse_auto_config(struct hda_codec *codec)
4935{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004936 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004937 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4938 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004939}
4940
Takashi Iwai1d045db2011-07-07 18:23:21 +02004941enum {
4942 ALC660VD_FIX_ASUS_GPIO1
4943};
4944
4945/* reset GPIO1 */
4946static const struct alc_fixup alc861vd_fixups[] = {
4947 [ALC660VD_FIX_ASUS_GPIO1] = {
4948 .type = ALC_FIXUP_VERBS,
4949 .v.verbs = (const struct hda_verb[]) {
4950 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
4951 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4952 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4953 { }
4954 }
4955 },
4956};
4957
4958static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
4959 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
4960 {}
4961};
4962
4963static const struct hda_verb alc660vd_eapd_verbs[] = {
4964 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
4965 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
4966 { }
4967};
4968
4969/*
4970 */
4971#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4972#include "alc861vd_quirks.c"
4973#endif
4974
4975static int patch_alc861vd(struct hda_codec *codec)
4976{
4977 struct alc_spec *spec;
4978 int err, board_config;
4979
4980 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4981 if (spec == NULL)
4982 return -ENOMEM;
4983
4984 codec->spec = spec;
4985
4986 spec->mixer_nid = 0x0b;
4987
4988 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
4989 alc861vd_models, alc861vd_cfg_tbl);
4990
4991 if (board_config < 0) {
4992 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4993 codec->chip_name);
4994 board_config = ALC_MODEL_AUTO;
4995 }
4996
4997 if (board_config == ALC_MODEL_AUTO) {
4998 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
4999 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5000 }
5001
5002 if (board_config == ALC_MODEL_AUTO) {
5003 /* automatic parse from the BIOS config */
5004 err = alc861vd_parse_auto_config(codec);
5005 if (err < 0) {
5006 alc_free(codec);
5007 return err;
5008 }
5009#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5010 else if (!err) {
5011 printk(KERN_INFO
5012 "hda_codec: Cannot set up configuration "
5013 "from BIOS. Using base mode...\n");
5014 board_config = ALC861VD_3ST;
5015 }
5016#endif
5017 }
5018
Takashi Iwai1d045db2011-07-07 18:23:21 +02005019 if (board_config != ALC_MODEL_AUTO)
5020 setup_preset(codec, &alc861vd_presets[board_config]);
5021
5022 if (codec->vendor_id == 0x10ec0660) {
5023 /* always turn on EAPD */
5024 add_verb(spec, alc660vd_eapd_verbs);
5025 }
5026
Takashi Iwai60a6a842011-07-27 14:01:24 +02005027 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005028 alc_auto_fill_adc_caps(codec);
5029 alc_rebuild_imux_for_auto_mic(codec);
5030 alc_remove_invalid_adc_nids(codec);
5031 }
5032
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005033 if (!spec->no_analog && !spec->cap_mixer)
5034 set_capture_mixer(codec);
5035
5036 if (!spec->no_analog) {
5037 err = snd_hda_attach_beep_device(codec, 0x23);
5038 if (err < 0) {
5039 alc_free(codec);
5040 return err;
5041 }
5042 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5043 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005044
5045 spec->vmaster_nid = 0x02;
5046
5047 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5048
5049 codec->patch_ops = alc_patch_ops;
5050
5051 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005052 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005053 spec->shutup = alc_eapd_shutup;
5054#ifdef CONFIG_SND_HDA_POWER_SAVE
5055 if (!spec->loopback.amplist)
5056 spec->loopback.amplist = alc861vd_loopbacks;
5057#endif
5058
5059 return 0;
5060}
5061
5062/*
5063 * ALC662 support
5064 *
5065 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5066 * configuration. Each pin widget can choose any input DACs and a mixer.
5067 * Each ADC is connected from a mixer of all inputs. This makes possible
5068 * 6-channel independent captures.
5069 *
5070 * In addition, an independent DAC for the multi-playback (not used in this
5071 * driver yet).
5072 */
5073#ifdef CONFIG_SND_HDA_POWER_SAVE
5074#define alc662_loopbacks alc880_loopbacks
5075#endif
5076
5077/*
5078 * BIOS auto configuration
5079 */
5080
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005081static int alc662_parse_auto_config(struct hda_codec *codec)
5082{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005083 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005084 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5085 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5086 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005087
Kailang Yang6227cdc2010-02-25 08:36:52 +01005088 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5089 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005090 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005091 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005092 ssids = alc662_ssids;
5093 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005094}
5095
Todd Broch6be79482010-12-07 16:51:05 -08005096static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005097 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005098{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005099 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005100 return;
Todd Broch6be79482010-12-07 16:51:05 -08005101 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5102 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5103 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5104 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5105 (0 << AC_AMPCAP_MUTE_SHIFT)))
5106 printk(KERN_WARNING
5107 "hda_codec: failed to override amp caps for NID 0x2\n");
5108}
5109
David Henningsson6cb3b702010-09-09 08:51:44 +02005110enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005111 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005112 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005113 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005114 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005115 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005116 ALC662_FIXUP_HP_RP5800,
David Henningsson6cb3b702010-09-09 08:51:44 +02005117};
5118
5119static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005120 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005121 .type = ALC_FIXUP_PINS,
5122 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005123 { 0x15, 0x99130112 }, /* subwoofer */
5124 { }
5125 }
5126 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005127 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005128 .type = ALC_FIXUP_PINS,
5129 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005130 { 0x17, 0x99130112 }, /* subwoofer */
5131 { }
5132 }
5133 },
Todd Broch6be79482010-12-07 16:51:05 -08005134 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005135 .type = ALC_FIXUP_FUNC,
5136 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005137 },
5138 [ALC662_FIXUP_CZC_P10T] = {
5139 .type = ALC_FIXUP_VERBS,
5140 .v.verbs = (const struct hda_verb[]) {
5141 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5142 {}
5143 }
5144 },
David Henningsson94024cd2011-04-29 14:10:55 +02005145 [ALC662_FIXUP_SKU_IGNORE] = {
5146 .type = ALC_FIXUP_SKU,
5147 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005148 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005149 [ALC662_FIXUP_HP_RP5800] = {
5150 .type = ALC_FIXUP_PINS,
5151 .v.pins = (const struct alc_pincfg[]) {
5152 { 0x14, 0x0221201f }, /* HP out */
5153 { }
5154 },
5155 .chained = true,
5156 .chain_id = ALC662_FIXUP_SKU_IGNORE
5157 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005158};
5159
Takashi Iwaia9111322011-05-02 11:30:18 +02005160static const struct snd_pci_quirk alc662_fixup_tbl[] = {
David Henningssona6c47a82011-02-10 15:39:19 +01005161 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005162 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005163 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005164 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005165 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005166 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005167 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005168 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02005169 {}
5170};
5171
Todd Broch6be79482010-12-07 16:51:05 -08005172static const struct alc_model_fixup alc662_fixup_models[] = {
5173 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
5174 {}
5175};
David Henningsson6cb3b702010-09-09 08:51:44 +02005176
5177
Takashi Iwai1d045db2011-07-07 18:23:21 +02005178/*
5179 */
5180#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5181#include "alc662_quirks.c"
5182#endif
5183
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005184static int patch_alc662(struct hda_codec *codec)
5185{
5186 struct alc_spec *spec;
5187 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02005188 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005189
5190 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5191 if (!spec)
5192 return -ENOMEM;
5193
5194 codec->spec = spec;
5195
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005196 spec->mixer_nid = 0x0b;
5197
Kailang Yangda00c242010-03-19 11:23:45 +01005198 alc_auto_parse_customize_define(codec);
5199
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005200 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5201
Kailang Yang693194f2010-10-21 08:51:48 +02005202 coef = alc_read_coef_idx(codec, 0);
5203 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005204 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005205 else if (coef & (1 << 14) &&
5206 codec->bus->pci->subsystem_vendor == 0x1025 &&
5207 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005208 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005209 else if (coef == 0x4011)
5210 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005211
Takashi Iwai1d045db2011-07-07 18:23:21 +02005212 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
5213 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005214 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005215 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5216 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005217 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005218 }
5219
Takashi Iwai1d045db2011-07-07 18:23:21 +02005220 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005221 alc_pick_fixup(codec, alc662_fixup_models,
5222 alc662_fixup_tbl, alc662_fixups);
5223 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005224 /* automatic parse from the BIOS config */
5225 err = alc662_parse_auto_config(codec);
5226 if (err < 0) {
5227 alc_free(codec);
5228 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005229 }
5230#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5231 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005232 printk(KERN_INFO
5233 "hda_codec: Cannot set up configuration "
5234 "from BIOS. Using base mode...\n");
5235 board_config = ALC662_3ST_2ch_DIG;
5236 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005237#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005238 }
5239
Takashi Iwai1d045db2011-07-07 18:23:21 +02005240 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005241 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005242
Takashi Iwai60a6a842011-07-27 14:01:24 +02005243 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005244 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005245 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005246 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005247 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005248
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005249 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005250 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005251
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005252 if (!spec->no_analog && has_cdefine_beep(codec)) {
5253 err = snd_hda_attach_beep_device(codec, 0x1);
5254 if (err < 0) {
5255 alc_free(codec);
5256 return err;
5257 }
Kailang Yangda00c242010-03-19 11:23:45 +01005258 switch (codec->vendor_id) {
5259 case 0x10ec0662:
5260 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5261 break;
5262 case 0x10ec0272:
5263 case 0x10ec0663:
5264 case 0x10ec0665:
5265 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5266 break;
5267 case 0x10ec0273:
5268 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5269 break;
5270 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005271 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005272 spec->vmaster_nid = 0x02;
5273
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005274 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5275
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005276 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005277 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005278 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c7161532011-04-07 10:37:16 +02005279 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005280
Kailang Yangbf1b0222010-10-21 08:49:56 +02005281 alc_init_jacks(codec);
5282
Takashi Iwaicb53c622007-08-10 17:21:45 +02005283#ifdef CONFIG_SND_HDA_POWER_SAVE
5284 if (!spec->loopback.amplist)
5285 spec->loopback.amplist = alc662_loopbacks;
5286#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005287
5288 return 0;
5289}
5290
Kailang Yang274693f2009-12-03 10:07:50 +01005291static int patch_alc888(struct hda_codec *codec)
5292{
5293 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5294 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005295 if (codec->vendor_id == 0x10ec0887)
5296 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5297 else
5298 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005299 if (!codec->chip_name) {
5300 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005301 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005302 }
5303 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005304 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005305 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005306}
5307
Kailang Yangb478b992011-05-18 11:51:15 +02005308static int patch_alc899(struct hda_codec *codec)
5309{
5310 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5311 kfree(codec->chip_name);
5312 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5313 }
5314 return patch_alc882(codec);
5315}
5316
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005317/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005318 * ALC680 support
5319 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005320
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005321static int alc680_parse_auto_config(struct hda_codec *codec)
5322{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005323 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005324}
5325
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005326/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005327 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005328#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5329#include "alc680_quirks.c"
5330#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005331
5332static int patch_alc680(struct hda_codec *codec)
5333{
5334 struct alc_spec *spec;
5335 int board_config;
5336 int err;
5337
5338 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5339 if (spec == NULL)
5340 return -ENOMEM;
5341
5342 codec->spec = spec;
5343
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005344 /* ALC680 has no aa-loopback mixer */
5345
Takashi Iwai1d045db2011-07-07 18:23:21 +02005346 board_config = alc_board_config(codec, ALC680_MODEL_LAST,
5347 alc680_models, alc680_cfg_tbl);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005348
Takashi Iwai1d045db2011-07-07 18:23:21 +02005349 if (board_config < 0) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005350 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5351 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005352 board_config = ALC_MODEL_AUTO;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005353 }
5354
Takashi Iwai1d045db2011-07-07 18:23:21 +02005355 if (board_config == ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005356 /* automatic parse from the BIOS config */
5357 err = alc680_parse_auto_config(codec);
5358 if (err < 0) {
5359 alc_free(codec);
5360 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005361 }
5362#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5363 else if (!err) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005364 printk(KERN_INFO
5365 "hda_codec: Cannot set up configuration "
5366 "from BIOS. Using base mode...\n");
5367 board_config = ALC680_BASE;
5368 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005369#endif
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005370 }
5371
Takashi Iwai1d045db2011-07-07 18:23:21 +02005372 if (board_config != ALC_MODEL_AUTO) {
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005373 setup_preset(codec, &alc680_presets[board_config]);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005374#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
Takashi Iwai21268962011-07-07 15:01:13 +02005375 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005376#endif
Takashi Iwai21268962011-07-07 15:01:13 +02005377 }
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005378
Takashi Iwai60a6a842011-07-27 14:01:24 +02005379 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005380 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005381 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005382 alc_remove_invalid_adc_nids(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005383 }
5384
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005385 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005386 set_capture_mixer(codec);
5387
5388 spec->vmaster_nid = 0x02;
5389
5390 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005391 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005392 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005393
5394 return 0;
5395}
5396
5397/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398 * patch entries
5399 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005400static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005401 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005403 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005404 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005405 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005406 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005407 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005408 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005409 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005410 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005411 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005412 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005413 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5414 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5415 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005416 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005417 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005418 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5419 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005420 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005421 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005422 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005423 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005424 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005425 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02005426 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005427 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005428 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005429 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005430 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005431 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005432 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005433 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai4953550a2009-06-30 15:28:30 +02005434 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005435 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02005436 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005437 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005438 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005439 {} /* terminator */
5440};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005441
5442MODULE_ALIAS("snd-hda-codec-id:10ec*");
5443
5444MODULE_LICENSE("GPL");
5445MODULE_DESCRIPTION("Realtek HD-audio codec");
5446
5447static struct hda_codec_preset_list realtek_list = {
5448 .preset = snd_hda_preset_realtek,
5449 .owner = THIS_MODULE,
5450};
5451
5452static int __init patch_realtek_init(void)
5453{
5454 return snd_hda_add_codec_preset(&realtek_list);
5455}
5456
5457static void __exit patch_realtek_exit(void)
5458{
5459 snd_hda_delete_codec_preset(&realtek_list);
5460}
5461
5462module_init(patch_realtek_init)
5463module_exit(patch_realtek_exit)