blob: e0ecf5a5b097c8d0cdce67a4d9260ad6495739ef [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
Takashi Iwai1d045db2011-07-07 18:23:21 +02004 * HD audio interface patch for Realtek ALC codecs
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Kailang Yangdf694da2005-12-05 19:42:22 +01006 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Takashi Iwai <tiwai@suse.de>
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01009 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020031#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "hda_codec.h"
33#include "hda_local.h"
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090034#include "hda_beep.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Takashi Iwai1d045db2011-07-07 18:23:21 +020036/* unsol event tags */
37#define ALC_FRONT_EVENT 0x01
38#define ALC_DCVOL_EVENT 0x02
39#define ALC_HP_EVENT 0x04
40#define ALC_MIC_EVENT 0x08
Takashi Iwaid4a86d82010-06-23 17:51:26 +020041
Kailang Yangdf694da2005-12-05 19:42:22 +010042/* for GPIO Poll */
43#define GPIO_MASK 0x03
44
Takashi Iwai4a79ba32009-04-22 16:31:35 +020045/* extra amp-initialization sequence types */
46enum {
47 ALC_INIT_NONE,
48 ALC_INIT_DEFAULT,
49 ALC_INIT_GPIO1,
50 ALC_INIT_GPIO2,
51 ALC_INIT_GPIO3,
52};
53
Kailang Yangda00c242010-03-19 11:23:45 +010054struct alc_customize_define {
55 unsigned int sku_cfg;
56 unsigned char port_connectivity;
57 unsigned char check_sum;
58 unsigned char customization;
59 unsigned char external_amp;
60 unsigned int enable_pcbeep:1;
61 unsigned int platform_type:1;
62 unsigned int swap:1;
63 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020064 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010065};
66
Takashi Iwaib5bfbc62011-01-13 14:22:32 +010067struct alc_fixup;
68
Takashi Iwaice764ab2011-04-27 16:35:23 +020069struct alc_multi_io {
70 hda_nid_t pin; /* multi-io widget pin NID */
71 hda_nid_t dac; /* DAC to be connected */
72 unsigned int ctl_in; /* cached input-pin control value */
73};
74
Takashi Iwaid922b512011-04-28 12:18:53 +020075enum {
Takashi Iwai3b8510c2011-04-28 14:03:24 +020076 ALC_AUTOMUTE_PIN, /* change the pin control */
77 ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
78 ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
Takashi Iwaid922b512011-04-28 12:18:53 +020079};
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081struct alc_spec {
82 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020083 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 unsigned int num_mixers;
Takashi Iwaia9111322011-05-02 11:30:18 +020085 const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010086 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Takashi Iwai2d9c6482009-10-13 08:06:55 +020088 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +020089 * don't forget NULL
90 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +020091 */
92 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Takashi Iwaiaa563af2009-07-31 10:05:11 +020094 char stream_name_analog[32]; /* analog PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +020095 const struct hda_pcm_stream *stream_analog_playback;
96 const struct hda_pcm_stream *stream_analog_capture;
97 const struct hda_pcm_stream *stream_analog_alt_playback;
98 const struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200100 char stream_name_digital[32]; /* digital PCM stream */
Takashi Iwaia9111322011-05-02 11:30:18 +0200101 const struct hda_pcm_stream *stream_digital_playback;
102 const struct hda_pcm_stream *stream_digital_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200105 struct hda_multi_out multiout; /* playback set-up
106 * max_channels, dacs must be set
107 * dig_out_nid and hp_nid are optional
108 */
Takashi Iwai63300792008-01-24 15:31:36 +0100109 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100110 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100111 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 /* capture */
114 unsigned int num_adc_nids;
Takashi Iwai4c6d72d2011-05-02 11:30:18 +0200115 const hda_nid_t *adc_nids;
116 const hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200117 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Takashi Iwai1f0f4b82011-06-27 10:52:59 +0200118 hda_nid_t mixer_nid; /* analog-mixer NID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Takashi Iwai840b64c2010-07-13 22:49:01 +0200120 /* capture setup for dynamic dual-adc switch */
Takashi Iwai840b64c2010-07-13 22:49:01 +0200121 hda_nid_t cur_adc;
122 unsigned int cur_adc_stream_tag;
123 unsigned int cur_adc_format;
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200126 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 const struct hda_input_mux *input_mux;
128 unsigned int cur_mux[3];
Takashi Iwai21268962011-07-07 15:01:13 +0200129 hda_nid_t ext_mic_pin;
130 hda_nid_t dock_mic_pin;
131 hda_nid_t int_mic_pin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100134 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200136 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200137 int const_channel_count;
138 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100141 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200142
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200143 /* dynamic controls, init_verbs and input_mux */
144 struct auto_pin_cfg autocfg;
Kailang Yangda00c242010-03-19 11:23:45 +0100145 struct alc_customize_define cdefine;
Takashi Iwai603c4012008-07-30 15:01:44 +0200146 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200147 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200148 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai49535502009-06-30 15:28:30 +0200149 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
150 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai21268962011-07-07 15:01:13 +0200151 hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
152 unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
153 int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
Takashi Iwai834be882006-03-01 14:16:17 +0100154
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100155 /* hooks */
156 void (*init_hook)(struct hda_codec *codec);
157 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100158#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500159 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100160#endif
Takashi Iwai1c716152011-04-07 10:37:16 +0200161 void (*shutup)(struct hda_codec *codec);
Takashi Iwai24519912011-08-16 15:08:49 +0200162 void (*automute_hook)(struct hda_codec *codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100163
Takashi Iwai834be882006-03-01 14:16:17 +0100164 /* for pin sensing */
Takashi Iwai834be882006-03-01 14:16:17 +0100165 unsigned int jack_present: 1;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200166 unsigned int line_jack_present:1;
Takashi Iwaie9427962011-04-28 15:46:07 +0200167 unsigned int master_mute:1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200168 unsigned int auto_mic:1;
Takashi Iwai21268962011-07-07 15:01:13 +0200169 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
Takashi Iwaid922b512011-04-28 12:18:53 +0200170 unsigned int automute:1; /* HP automute enabled */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200171 unsigned int detect_line:1; /* Line-out detection enabled */
172 unsigned int automute_lines:1; /* automute line-out as well */
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200173 unsigned int automute_hp_lo:1; /* both HP and LO available */
Takashi Iwaicb53c622007-08-10 17:21:45 +0200174
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100175 /* other flags */
176 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai21268962011-07-07 15:01:13 +0200177 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai584c0c42011-03-10 12:51:11 +0100178 unsigned int single_input_src:1;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +0200179 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
Takashi Iwaid922b512011-04-28 12:18:53 +0200180
181 /* auto-mute control */
182 int automute_mode;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200183 hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
Takashi Iwaid922b512011-04-28 12:18:53 +0200184
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200185 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200186 int codec_variant; /* flag for other variants */
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100187
Takashi Iwai2134ea42008-01-10 16:53:55 +0100188 /* for virtual master */
189 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200190#ifdef CONFIG_SND_HDA_POWER_SAVE
191 struct hda_loopback_check loopback;
192#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200193
194 /* for PLL fix */
195 hda_nid_t pll_nid;
196 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +0100197
198 /* fix-up list */
199 int fixup_id;
200 const struct alc_fixup *fixup_list;
201 const char *fixup_name;
Takashi Iwaice764ab2011-04-27 16:35:23 +0200202
203 /* multi-io */
204 int multi_ios;
205 struct alc_multi_io multi_io[4];
Takashi Iwai23c09b02011-08-19 09:05:35 +0200206
207 /* bind volumes */
208 struct snd_array bind_ctls;
Kailang Yangdf694da2005-12-05 19:42:22 +0100209};
210
Takashi Iwai1d045db2011-07-07 18:23:21 +0200211#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
Takashi Iwai44c02402011-07-08 15:14:19 +0200213static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
214 int dir, unsigned int bits)
215{
216 if (!nid)
217 return false;
218 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
219 if (query_amp_caps(codec, nid, dir) & bits)
220 return true;
221 return false;
222}
223
224#define nid_has_mute(codec, nid, dir) \
225 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
226#define nid_has_volume(codec, nid, dir) \
227 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229/*
230 * input MUX handling
231 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200232static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
233 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234{
235 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
236 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200237 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
238 if (mux_idx >= spec->num_mux_defs)
239 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100240 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
241 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200242 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243}
244
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200245static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
246 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247{
248 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
249 struct alc_spec *spec = codec->spec;
250 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
251
252 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
253 return 0;
254}
255
Takashi Iwai21268962011-07-07 15:01:13 +0200256static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257{
Takashi Iwai21268962011-07-07 15:01:13 +0200258 struct alc_spec *spec = codec->spec;
259 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
260
261 if (spec->cur_adc && spec->cur_adc != new_adc) {
262 /* stream is running, let's swap the current ADC */
263 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
264 spec->cur_adc = new_adc;
265 snd_hda_codec_setup_stream(codec, new_adc,
266 spec->cur_adc_stream_tag, 0,
267 spec->cur_adc_format);
268 return true;
269 }
270 return false;
271}
272
273/* select the given imux item; either unmute exclusively or select the route */
274static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
275 unsigned int idx, bool force)
276{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100278 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100279 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200280 int i, type;
281 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Takashi Iwaicd896c32008-11-18 12:36:33 +0100283 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
284 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100285 if (!imux->num_items && mux_idx > 0)
286 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100287
Takashi Iwai21268962011-07-07 15:01:13 +0200288 if (idx >= imux->num_items)
289 idx = imux->num_items - 1;
290 if (spec->cur_mux[adc_idx] == idx && !force)
291 return 0;
292 spec->cur_mux[adc_idx] = idx;
293
294 if (spec->dyn_adc_switch) {
295 alc_dyn_adc_pcm_resetup(codec, idx);
296 adc_idx = spec->dyn_adc_idx[idx];
297 }
298
299 nid = spec->capsrc_nids ?
300 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
301
302 /* no selection? */
303 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
304 return 1;
305
Takashi Iwaia22d5432009-07-27 12:54:26 +0200306 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200307 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100308 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100309 for (i = 0; i < imux->num_items; i++) {
310 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
311 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
312 imux->items[i].index,
313 HDA_AMP_MUTE, v);
314 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100315 } else {
316 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200317 snd_hda_codec_write_cache(codec, nid, 0,
318 AC_VERB_SET_CONNECT_SEL,
319 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100320 }
Takashi Iwai21268962011-07-07 15:01:13 +0200321 return 1;
322}
323
324static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
325 struct snd_ctl_elem_value *ucontrol)
326{
327 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
328 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
329 return alc_mux_select(codec, adc_idx,
330 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100331}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200332
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100334 * set up the input pin config (depending on the given auto-pin type)
335 */
336static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
337 int auto_pin_type)
338{
339 unsigned int val = PIN_IN;
340
Takashi Iwai86e29592010-09-09 14:50:17 +0200341 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100342 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200343 unsigned int oldval;
344 oldval = snd_hda_codec_read(codec, nid, 0,
345 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100346 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100347 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200348 /* if the default pin setup is vref50, we give it priority */
349 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100350 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200351 else if (pincap & AC_PINCAP_VREF_50)
352 val = PIN_VREF50;
353 else if (pincap & AC_PINCAP_VREF_100)
354 val = PIN_VREF100;
355 else if (pincap & AC_PINCAP_VREF_GRD)
356 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100357 }
358 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
359}
360
361/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200362 * Append the given mixer and verb elements for the later use
363 * The mixer array is referred in build_controls(), and init_verbs are
364 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100365 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200366static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100367{
368 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
369 return;
370 spec->mixers[spec->num_mixers++] = mix;
371}
372
373static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
374{
375 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
376 return;
377 spec->init_verbs[spec->num_init_verbs++] = verb;
378}
379
380/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200381 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100382 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200383/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200384static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200385 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
386 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
387 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
388 { }
389};
390
Takashi Iwaia9111322011-05-02 11:30:18 +0200391static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200392 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
393 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
394 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
395 { }
396};
397
Takashi Iwaia9111322011-05-02 11:30:18 +0200398static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200399 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
400 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
401 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
402 { }
403};
404
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200405/*
406 * Fix hardware PLL issue
407 * On some codecs, the analog PLL gating control must be off while
408 * the default value is 1.
409 */
410static void alc_fix_pll(struct hda_codec *codec)
411{
412 struct alc_spec *spec = codec->spec;
413 unsigned int val;
414
415 if (!spec->pll_nid)
416 return;
417 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
418 spec->pll_coef_idx);
419 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
420 AC_VERB_GET_PROC_COEF, 0);
421 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
422 spec->pll_coef_idx);
423 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
424 val & ~(1 << spec->pll_coef_bit));
425}
426
427static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
428 unsigned int coef_idx, unsigned int coef_bit)
429{
430 struct alc_spec *spec = codec->spec;
431 spec->pll_nid = nid;
432 spec->pll_coef_idx = coef_idx;
433 spec->pll_coef_bit = coef_bit;
434 alc_fix_pll(codec);
435}
436
Takashi Iwai1d045db2011-07-07 18:23:21 +0200437/*
438 * Jack-reporting via input-jack layer
439 */
440
441/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200442static int alc_init_jacks(struct hda_codec *codec)
443{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100444#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200445 struct alc_spec *spec = codec->spec;
446 int err;
447 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200448 unsigned int mic_nid = spec->ext_mic_pin;
449 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200450
Takashi Iwai265a0242010-09-21 11:26:21 +0200451 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100452 err = snd_hda_input_jack_add(codec, hp_nid,
453 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200454 if (err < 0)
455 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100456 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200457 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200458
Takashi Iwai265a0242010-09-21 11:26:21 +0200459 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100460 err = snd_hda_input_jack_add(codec, mic_nid,
461 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200462 if (err < 0)
463 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100464 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200465 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200466 if (dock_nid) {
467 err = snd_hda_input_jack_add(codec, dock_nid,
468 SND_JACK_MICROPHONE, NULL);
469 if (err < 0)
470 return err;
471 snd_hda_input_jack_report(codec, dock_nid);
472 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100473#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200474 return 0;
475}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200476
Takashi Iwai1d045db2011-07-07 18:23:21 +0200477/*
478 * Jack detections for HP auto-mute and mic-switch
479 */
480
481/* check each pin in the given array; returns true if any of them is plugged */
482static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200483{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200484 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200485
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200486 for (i = 0; i < num_pins; i++) {
487 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200488 if (!nid)
489 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100490 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200491 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200492 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200493 return present;
494}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200495
Takashi Iwai1d045db2011-07-07 18:23:21 +0200496/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200497static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200498 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200499{
500 struct alc_spec *spec = codec->spec;
501 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200502 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200503 int i;
504
505 for (i = 0; i < num_pins; i++) {
506 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200507 if (!nid)
508 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200509 switch (spec->automute_mode) {
510 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200511 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200512 AC_VERB_SET_PIN_WIDGET_CONTROL,
513 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200514 break;
515 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200516 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200517 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200518 break;
519 case ALC_AUTOMUTE_MIXER:
520 nid = spec->automute_mixer_nid[i];
521 if (!nid)
522 break;
523 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200524 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200525 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200526 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200527 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200528 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200529 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200530}
531
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200532/* Toggle internal speakers muting */
533static void update_speakers(struct hda_codec *codec)
534{
535 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200536 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200537
Takashi Iwaic0a20262011-06-10 15:28:15 +0200538 /* Control HP pins/amps depending on master_mute state;
539 * in general, HP pins/amps control should be enabled in all cases,
540 * but currently set only for master_mute, just to be safe
541 */
542 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
543 spec->autocfg.hp_pins, spec->master_mute, true);
544
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200545 if (!spec->automute)
546 on = 0;
547 else
548 on = spec->jack_present | spec->line_jack_present;
549 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200550 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200551 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200552
553 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200554 /* if LO is a copy of either HP or Speaker, don't need to handle it */
555 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
556 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200557 return;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200558 if (!spec->automute_lines || !spec->automute)
559 on = 0;
560 else
561 on = spec->jack_present;
562 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200563 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200564 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200565}
566
Takashi Iwai24519912011-08-16 15:08:49 +0200567static void call_update_speakers(struct hda_codec *codec)
568{
569 struct alc_spec *spec = codec->spec;
570 if (spec->automute_hook)
571 spec->automute_hook(codec);
572 else
573 update_speakers(codec);
574}
575
Takashi Iwai1d045db2011-07-07 18:23:21 +0200576/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200577static void alc_hp_automute(struct hda_codec *codec)
578{
579 struct alc_spec *spec = codec->spec;
580
581 if (!spec->automute)
582 return;
583 spec->jack_present =
584 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
585 spec->autocfg.hp_pins);
Takashi Iwai24519912011-08-16 15:08:49 +0200586 call_update_speakers(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200587}
588
Takashi Iwai1d045db2011-07-07 18:23:21 +0200589/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200590static void alc_line_automute(struct hda_codec *codec)
591{
592 struct alc_spec *spec = codec->spec;
593
594 if (!spec->automute || !spec->detect_line)
595 return;
596 spec->line_jack_present =
597 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
598 spec->autocfg.line_out_pins);
Takashi Iwai24519912011-08-16 15:08:49 +0200599 call_update_speakers(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200600}
601
Takashi Iwai8d087c72011-06-28 12:45:47 +0200602#define get_connection_index(codec, mux, nid) \
603 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200604
Takashi Iwai1d045db2011-07-07 18:23:21 +0200605/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200606static void alc_mic_automute(struct hda_codec *codec)
607{
608 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200609 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200610
Takashi Iwai21268962011-07-07 15:01:13 +0200611 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200612 return;
613 if (snd_BUG_ON(!spec->adc_nids))
614 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200615 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200616 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200617
Takashi Iwai21268962011-07-07 15:01:13 +0200618 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
619 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
620 else if (spec->dock_mic_idx >= 0 &&
621 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
622 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
623 else
624 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200625
Takashi Iwai21268962011-07-07 15:01:13 +0200626 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
627 if (spec->dock_mic_idx >= 0)
628 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200629}
630
Kailang Yangc9b58002007-10-16 14:30:01 +0200631/* unsolicited event for HP jack sensing */
632static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
633{
634 if (codec->vendor_id == 0x10ec0880)
635 res >>= 28;
636 else
637 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200638 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200639 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200640 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200641 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200642 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200643 alc_line_automute(codec);
644 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200645 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200646 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200647 break;
648 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200649}
650
Takashi Iwai1d045db2011-07-07 18:23:21 +0200651/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200652static void alc_inithook(struct hda_codec *codec)
653{
Takashi Iwaid922b512011-04-28 12:18:53 +0200654 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200655 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200656 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200657}
658
Kailang Yangf9423e72008-05-27 12:32:25 +0200659/* additional initialization for ALC888 variants */
660static void alc888_coef_init(struct hda_codec *codec)
661{
662 unsigned int tmp;
663
664 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
665 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
666 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100667 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200668 /* alc888S-VC */
669 snd_hda_codec_read(codec, 0x20, 0,
670 AC_VERB_SET_PROC_COEF, 0x830);
671 else
672 /* alc888-VB */
673 snd_hda_codec_read(codec, 0x20, 0,
674 AC_VERB_SET_PROC_COEF, 0x3030);
675}
676
Takashi Iwai1d045db2011-07-07 18:23:21 +0200677/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200678static void alc889_coef_init(struct hda_codec *codec)
679{
680 unsigned int tmp;
681
682 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
683 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
684 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
685 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
686}
687
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100688/* turn on/off EAPD control (only if available) */
689static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
690{
691 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
692 return;
693 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
694 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
695 on ? 2 : 0);
696}
697
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200698/* turn on/off EAPD controls of the codec */
699static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
700{
701 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200702 static hda_nid_t pins[] = {
703 0x0f, 0x10, 0x14, 0x15, 0
704 };
705 hda_nid_t *p;
706 for (p = pins; *p; p++)
707 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200708}
709
Takashi Iwai1c716152011-04-07 10:37:16 +0200710/* generic shutup callback;
711 * just turning off EPAD and a little pause for avoiding pop-noise
712 */
713static void alc_eapd_shutup(struct hda_codec *codec)
714{
715 alc_auto_setup_eapd(codec, false);
716 msleep(200);
717}
718
Takashi Iwai1d045db2011-07-07 18:23:21 +0200719/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200720static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200721{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200722 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200723
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200724 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200725 switch (type) {
726 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200727 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
728 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200729 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200730 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
731 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200732 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200733 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
734 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200735 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200736 switch (codec->vendor_id) {
737 case 0x10ec0260:
738 snd_hda_codec_write(codec, 0x1a, 0,
739 AC_VERB_SET_COEF_INDEX, 7);
740 tmp = snd_hda_codec_read(codec, 0x1a, 0,
741 AC_VERB_GET_PROC_COEF, 0);
742 snd_hda_codec_write(codec, 0x1a, 0,
743 AC_VERB_SET_COEF_INDEX, 7);
744 snd_hda_codec_write(codec, 0x1a, 0,
745 AC_VERB_SET_PROC_COEF,
746 tmp | 0x2010);
747 break;
748 case 0x10ec0262:
749 case 0x10ec0880:
750 case 0x10ec0882:
751 case 0x10ec0883:
752 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100753 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100754 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200755 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200756 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200757 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200758 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200759 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100760#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200761 case 0x10ec0267:
762 case 0x10ec0268:
763 snd_hda_codec_write(codec, 0x20, 0,
764 AC_VERB_SET_COEF_INDEX, 7);
765 tmp = snd_hda_codec_read(codec, 0x20, 0,
766 AC_VERB_GET_PROC_COEF, 0);
767 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200768 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200769 snd_hda_codec_write(codec, 0x20, 0,
770 AC_VERB_SET_PROC_COEF,
771 tmp | 0x3000);
772 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100773#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200774 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200775 break;
776 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200777}
Kailang Yangea1fb292008-08-26 12:58:38 +0200778
Takashi Iwai1d045db2011-07-07 18:23:21 +0200779/*
780 * Auto-Mute mode mixer enum support
781 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200782static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
783 struct snd_ctl_elem_info *uinfo)
784{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200785 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
786 struct alc_spec *spec = codec->spec;
787 static const char * const texts2[] = {
788 "Disabled", "Enabled"
789 };
790 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200791 "Disabled", "Speaker Only", "Line-Out+Speaker"
792 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200793 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200794
795 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
796 uinfo->count = 1;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200797 if (spec->automute_hp_lo) {
798 uinfo->value.enumerated.items = 3;
799 texts = texts3;
800 } else {
801 uinfo->value.enumerated.items = 2;
802 texts = texts2;
803 }
804 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
805 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200806 strcpy(uinfo->value.enumerated.name,
807 texts[uinfo->value.enumerated.item]);
808 return 0;
809}
810
811static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
812 struct snd_ctl_elem_value *ucontrol)
813{
814 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
815 struct alc_spec *spec = codec->spec;
816 unsigned int val;
817 if (!spec->automute)
818 val = 0;
819 else if (!spec->automute_lines)
820 val = 1;
821 else
822 val = 2;
823 ucontrol->value.enumerated.item[0] = val;
824 return 0;
825}
826
827static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
828 struct snd_ctl_elem_value *ucontrol)
829{
830 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
831 struct alc_spec *spec = codec->spec;
832
833 switch (ucontrol->value.enumerated.item[0]) {
834 case 0:
835 if (!spec->automute)
836 return 0;
837 spec->automute = 0;
838 break;
839 case 1:
840 if (spec->automute && !spec->automute_lines)
841 return 0;
842 spec->automute = 1;
843 spec->automute_lines = 0;
844 break;
845 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200846 if (!spec->automute_hp_lo)
847 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200848 if (spec->automute && spec->automute_lines)
849 return 0;
850 spec->automute = 1;
851 spec->automute_lines = 1;
852 break;
853 default:
854 return -EINVAL;
855 }
Takashi Iwai24519912011-08-16 15:08:49 +0200856 call_update_speakers(codec);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200857 return 1;
858}
859
Takashi Iwaia9111322011-05-02 11:30:18 +0200860static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200861 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
862 .name = "Auto-Mute Mode",
863 .info = alc_automute_mode_info,
864 .get = alc_automute_mode_get,
865 .put = alc_automute_mode_put,
866};
867
Takashi Iwai1d045db2011-07-07 18:23:21 +0200868static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
869{
870 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
871 return snd_array_new(&spec->kctls);
872}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200873
874static int alc_add_automute_mode_enum(struct hda_codec *codec)
875{
876 struct alc_spec *spec = codec->spec;
877 struct snd_kcontrol_new *knew;
878
879 knew = alc_kcontrol_new(spec);
880 if (!knew)
881 return -ENOMEM;
882 *knew = alc_automute_mode_enum;
883 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
884 if (!knew->name)
885 return -ENOMEM;
886 return 0;
887}
888
Takashi Iwai1d045db2011-07-07 18:23:21 +0200889/*
890 * Check the availability of HP/line-out auto-mute;
891 * Set up appropriately if really supported
892 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200893static void alc_init_auto_hp(struct hda_codec *codec)
894{
895 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200896 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200897 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200898 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200899
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200900 if (cfg->hp_pins[0])
901 present++;
902 if (cfg->line_out_pins[0])
903 present++;
904 if (cfg->speaker_pins[0])
905 present++;
906 if (present < 2) /* need two different output types */
907 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200908 if (present == 3)
909 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200910
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200911 if (!cfg->speaker_pins[0] &&
912 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200913 memcpy(cfg->speaker_pins, cfg->line_out_pins,
914 sizeof(cfg->speaker_pins));
915 cfg->speaker_outs = cfg->line_outs;
916 }
917
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200918 if (!cfg->hp_pins[0] &&
919 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200920 memcpy(cfg->hp_pins, cfg->line_out_pins,
921 sizeof(cfg->hp_pins));
922 cfg->hp_outs = cfg->line_outs;
923 }
924
925 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200926 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200927 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200928 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200929 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200930 nid);
931 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200932 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200933 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200934 spec->automute = 1;
935 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200936 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200937 if (spec->automute && cfg->line_out_pins[0] &&
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200938 cfg->speaker_pins[0] &&
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200939 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
940 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
941 for (i = 0; i < cfg->line_outs; i++) {
942 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200943 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200944 continue;
945 snd_printdd("realtek: Enable Line-Out auto-muting "
946 "on NID 0x%x\n", nid);
947 snd_hda_codec_write_cache(codec, nid, 0,
948 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200949 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200950 spec->detect_line = 1;
951 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200952 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200953 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200954
955 if (spec->automute) {
956 /* create a control for automute mode */
957 alc_add_automute_mode_enum(codec);
958 spec->unsol_event = alc_sku_unsol_event;
959 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200960}
961
Takashi Iwai1d045db2011-07-07 18:23:21 +0200962/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200963static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
964{
965 int i;
966 for (i = 0; i < nums; i++)
967 if (list[i] == nid)
968 return i;
969 return -1;
970}
971
Takashi Iwai1d045db2011-07-07 18:23:21 +0200972/* check whether dynamic ADC-switching is available */
973static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
974{
975 struct alc_spec *spec = codec->spec;
976 struct hda_input_mux *imux = &spec->private_imux[0];
977 int i, n, idx;
978 hda_nid_t cap, pin;
979
980 if (imux != spec->input_mux) /* no dynamic imux? */
981 return false;
982
983 for (n = 0; n < spec->num_adc_nids; n++) {
984 cap = spec->private_capsrc_nids[n];
985 for (i = 0; i < imux->num_items; i++) {
986 pin = spec->imux_pins[i];
987 if (!pin)
988 return false;
989 if (get_connection_index(codec, cap, pin) < 0)
990 break;
991 }
992 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +0200993 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +0200994 }
995
996 for (i = 0; i < imux->num_items; i++) {
997 pin = spec->imux_pins[i];
998 for (n = 0; n < spec->num_adc_nids; n++) {
999 cap = spec->private_capsrc_nids[n];
1000 idx = get_connection_index(codec, cap, pin);
1001 if (idx >= 0) {
1002 imux->items[i].index = idx;
1003 spec->dyn_adc_idx[i] = n;
1004 break;
1005 }
1006 }
1007 }
1008
1009 snd_printdd("realtek: enabling ADC switching\n");
1010 spec->dyn_adc_switch = 1;
1011 return true;
1012}
Takashi Iwai21268962011-07-07 15:01:13 +02001013
1014/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1015static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1016{
1017 struct alc_spec *spec = codec->spec;
1018 struct hda_input_mux *imux;
1019 static char * const texts[3] = {
1020 "Mic", "Internal Mic", "Dock Mic"
1021 };
1022 int i;
1023
1024 if (!spec->auto_mic)
1025 return false;
1026 imux = &spec->private_imux[0];
1027 if (spec->input_mux == imux)
1028 return true;
1029 spec->imux_pins[0] = spec->ext_mic_pin;
1030 spec->imux_pins[1] = spec->int_mic_pin;
1031 spec->imux_pins[2] = spec->dock_mic_pin;
1032 for (i = 0; i < 3; i++) {
1033 strcpy(imux->items[i].label, texts[i]);
1034 if (spec->imux_pins[i])
1035 imux->num_items = i + 1;
1036 }
1037 spec->num_mux_defs = 1;
1038 spec->input_mux = imux;
1039 return true;
1040}
1041
1042/* check whether all auto-mic pins are valid; setup indices if OK */
1043static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1044{
1045 struct alc_spec *spec = codec->spec;
1046 const struct hda_input_mux *imux;
1047
1048 if (!spec->auto_mic)
1049 return false;
1050 if (spec->auto_mic_valid_imux)
1051 return true; /* already checked */
1052
1053 /* fill up imux indices */
1054 if (!alc_check_dyn_adc_switch(codec)) {
1055 spec->auto_mic = 0;
1056 return false;
1057 }
1058
1059 imux = spec->input_mux;
1060 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1061 spec->imux_pins, imux->num_items);
1062 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1063 spec->imux_pins, imux->num_items);
1064 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1065 spec->imux_pins, imux->num_items);
1066 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1067 spec->auto_mic = 0;
1068 return false; /* no corresponding imux */
1069 }
1070
1071 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1072 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001073 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001074 if (spec->dock_mic_pin)
1075 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1076 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001077 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001078
1079 spec->auto_mic_valid_imux = 1;
1080 spec->auto_mic = 1;
1081 return true;
1082}
1083
Takashi Iwai1d045db2011-07-07 18:23:21 +02001084/*
1085 * Check the availability of auto-mic switch;
1086 * Set up if really supported
1087 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001088static void alc_init_auto_mic(struct hda_codec *codec)
1089{
1090 struct alc_spec *spec = codec->spec;
1091 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001092 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001093 int i;
1094
Takashi Iwai21268962011-07-07 15:01:13 +02001095 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1096
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001097 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001098 for (i = 0; i < cfg->num_inputs; i++) {
1099 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001100 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001101 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001102 switch (snd_hda_get_input_pin_attr(defcfg)) {
1103 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001104 if (fixed)
1105 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001106 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1107 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001108 fixed = nid;
1109 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001110 case INPUT_PIN_ATTR_UNUSED:
1111 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001112 case INPUT_PIN_ATTR_DOCK:
1113 if (dock)
1114 return; /* already occupied */
1115 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1116 return; /* invalid type */
1117 dock = nid;
1118 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001119 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001120 if (ext)
1121 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001122 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1123 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001124 ext = nid;
1125 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001126 }
1127 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001128 if (!ext && dock) {
1129 ext = dock;
1130 dock = 0;
1131 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001132 if (!ext || !fixed)
1133 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001134 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001135 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001136 if (dock && !is_jack_detectable(codec, dock))
1137 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001138
1139 /* check imux indices */
1140 spec->ext_mic_pin = ext;
1141 spec->int_mic_pin = fixed;
1142 spec->dock_mic_pin = dock;
1143
1144 spec->auto_mic = 1;
1145 if (!alc_auto_mic_check_imux(codec))
1146 return;
1147
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001148 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1149 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001150 spec->unsol_event = alc_sku_unsol_event;
1151}
1152
Takashi Iwai1d045db2011-07-07 18:23:21 +02001153/* check the availabilities of auto-mute and auto-mic switches */
1154static void alc_auto_check_switches(struct hda_codec *codec)
1155{
1156 alc_init_auto_hp(codec);
1157 alc_init_auto_mic(codec);
1158}
1159
1160/*
1161 * Realtek SSID verification
1162 */
1163
David Henningsson90622912010-10-14 14:50:18 +02001164/* Could be any non-zero and even value. When used as fixup, tells
1165 * the driver to ignore any present sku defines.
1166 */
1167#define ALC_FIXUP_SKU_IGNORE (2)
1168
Kailang Yangda00c242010-03-19 11:23:45 +01001169static int alc_auto_parse_customize_define(struct hda_codec *codec)
1170{
1171 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001172 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001173 struct alc_spec *spec = codec->spec;
1174
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001175 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1176
David Henningsson90622912010-10-14 14:50:18 +02001177 if (spec->cdefine.fixup) {
1178 ass = spec->cdefine.sku_cfg;
1179 if (ass == ALC_FIXUP_SKU_IGNORE)
1180 return -1;
1181 goto do_sku;
1182 }
1183
Kailang Yangda00c242010-03-19 11:23:45 +01001184 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001185 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001186 goto do_sku;
1187
1188 nid = 0x1d;
1189 if (codec->vendor_id == 0x10ec0260)
1190 nid = 0x17;
1191 ass = snd_hda_codec_get_pincfg(codec, nid);
1192
1193 if (!(ass & 1)) {
1194 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1195 codec->chip_name, ass);
1196 return -1;
1197 }
1198
1199 /* check sum */
1200 tmp = 0;
1201 for (i = 1; i < 16; i++) {
1202 if ((ass >> i) & 1)
1203 tmp++;
1204 }
1205 if (((ass >> 16) & 0xf) != tmp)
1206 return -1;
1207
1208 spec->cdefine.port_connectivity = ass >> 30;
1209 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1210 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1211 spec->cdefine.customization = ass >> 8;
1212do_sku:
1213 spec->cdefine.sku_cfg = ass;
1214 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1215 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1216 spec->cdefine.swap = (ass & 0x2) >> 1;
1217 spec->cdefine.override = ass & 0x1;
1218
1219 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1220 nid, spec->cdefine.sku_cfg);
1221 snd_printd("SKU: port_connectivity=0x%x\n",
1222 spec->cdefine.port_connectivity);
1223 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1224 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1225 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1226 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1227 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1228 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1229 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1230
1231 return 0;
1232}
1233
Takashi Iwai1d045db2011-07-07 18:23:21 +02001234/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001235static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1236{
Takashi Iwai21268962011-07-07 15:01:13 +02001237 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001238}
1239
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001240/* check subsystem ID and set up device-specific initialization;
1241 * return 1 if initialized, 0 if invalid SSID
1242 */
1243/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1244 * 31 ~ 16 : Manufacture ID
1245 * 15 ~ 8 : SKU ID
1246 * 7 ~ 0 : Assembly ID
1247 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1248 */
1249static int alc_subsystem_id(struct hda_codec *codec,
1250 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001251 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001252{
1253 unsigned int ass, tmp, i;
1254 unsigned nid;
1255 struct alc_spec *spec = codec->spec;
1256
David Henningsson90622912010-10-14 14:50:18 +02001257 if (spec->cdefine.fixup) {
1258 ass = spec->cdefine.sku_cfg;
1259 if (ass == ALC_FIXUP_SKU_IGNORE)
1260 return 0;
1261 goto do_sku;
1262 }
1263
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001264 ass = codec->subsystem_id & 0xffff;
1265 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1266 goto do_sku;
1267
1268 /* invalid SSID, check the special NID pin defcfg instead */
1269 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001270 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001271 * 29~21 : reserve
1272 * 20 : PCBEEP input
1273 * 19~16 : Check sum (15:1)
1274 * 15~1 : Custom
1275 * 0 : override
1276 */
1277 nid = 0x1d;
1278 if (codec->vendor_id == 0x10ec0260)
1279 nid = 0x17;
1280 ass = snd_hda_codec_get_pincfg(codec, nid);
1281 snd_printd("realtek: No valid SSID, "
1282 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001283 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001284 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001285 return 0;
1286 if ((ass >> 30) != 1) /* no physical connection */
1287 return 0;
1288
1289 /* check sum */
1290 tmp = 0;
1291 for (i = 1; i < 16; i++) {
1292 if ((ass >> i) & 1)
1293 tmp++;
1294 }
1295 if (((ass >> 16) & 0xf) != tmp)
1296 return 0;
1297do_sku:
1298 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1299 ass & 0xffff, codec->vendor_id);
1300 /*
1301 * 0 : override
1302 * 1 : Swap Jack
1303 * 2 : 0 --> Desktop, 1 --> Laptop
1304 * 3~5 : External Amplifier control
1305 * 7~6 : Reserved
1306 */
1307 tmp = (ass & 0x38) >> 3; /* external Amp control */
1308 switch (tmp) {
1309 case 1:
1310 spec->init_amp = ALC_INIT_GPIO1;
1311 break;
1312 case 3:
1313 spec->init_amp = ALC_INIT_GPIO2;
1314 break;
1315 case 7:
1316 spec->init_amp = ALC_INIT_GPIO3;
1317 break;
1318 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001319 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001320 spec->init_amp = ALC_INIT_DEFAULT;
1321 break;
1322 }
1323
1324 /* is laptop or Desktop and enable the function "Mute internal speaker
1325 * when the external headphone out jack is plugged"
1326 */
1327 if (!(ass & 0x8000))
1328 return 1;
1329 /*
1330 * 10~8 : Jack location
1331 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1332 * 14~13: Resvered
1333 * 15 : 1 --> enable the function "Mute internal speaker
1334 * when the external headphone out jack is plugged"
1335 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001336 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001337 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001338 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1339 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001340 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001341 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001342 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001343 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001344 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001345 else if (tmp == 3)
1346 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001347 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001348 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001349 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1350 spec->autocfg.line_outs))
1351 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001352 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001353 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001354 return 1;
1355}
Kailang Yangea1fb292008-08-26 12:58:38 +02001356
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001357/* Check the validity of ALC subsystem-id
1358 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1359static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001360{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001361 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001362 struct alc_spec *spec = codec->spec;
1363 snd_printd("realtek: "
1364 "Enable default setup for auto mode as fallback\n");
1365 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001366 }
Takashi Iwai21268962011-07-07 15:01:13 +02001367}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001368
Takashi Iwai41e41f12005-06-08 14:48:49 +02001369/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001370 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001371 */
1372
1373struct alc_pincfg {
1374 hda_nid_t nid;
1375 u32 val;
1376};
1377
Todd Broche1eb5f12010-12-06 11:19:51 -08001378struct alc_model_fixup {
1379 const int id;
1380 const char *name;
1381};
1382
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001383struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001384 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001385 bool chained;
1386 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001387 union {
1388 unsigned int sku;
1389 const struct alc_pincfg *pins;
1390 const struct hda_verb *verbs;
1391 void (*func)(struct hda_codec *codec,
1392 const struct alc_fixup *fix,
1393 int action);
1394 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001395};
1396
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001397enum {
1398 ALC_FIXUP_INVALID,
1399 ALC_FIXUP_SKU,
1400 ALC_FIXUP_PINS,
1401 ALC_FIXUP_VERBS,
1402 ALC_FIXUP_FUNC,
1403};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001404
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001405enum {
1406 ALC_FIXUP_ACT_PRE_PROBE,
1407 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001408 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001409};
1410
1411static void alc_apply_fixup(struct hda_codec *codec, int action)
1412{
1413 struct alc_spec *spec = codec->spec;
1414 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001415#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001416 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001417#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001418 int depth = 0;
1419
1420 if (!spec->fixup_list)
1421 return;
1422
1423 while (id >= 0) {
1424 const struct alc_fixup *fix = spec->fixup_list + id;
1425 const struct alc_pincfg *cfg;
1426
1427 switch (fix->type) {
1428 case ALC_FIXUP_SKU:
1429 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1430 break;;
1431 snd_printdd(KERN_INFO "hda_codec: %s: "
1432 "Apply sku override for %s\n",
1433 codec->chip_name, modelname);
1434 spec->cdefine.sku_cfg = fix->v.sku;
1435 spec->cdefine.fixup = 1;
1436 break;
1437 case ALC_FIXUP_PINS:
1438 cfg = fix->v.pins;
1439 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1440 break;
1441 snd_printdd(KERN_INFO "hda_codec: %s: "
1442 "Apply pincfg for %s\n",
1443 codec->chip_name, modelname);
1444 for (; cfg->nid; cfg++)
1445 snd_hda_codec_set_pincfg(codec, cfg->nid,
1446 cfg->val);
1447 break;
1448 case ALC_FIXUP_VERBS:
1449 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1450 break;
1451 snd_printdd(KERN_INFO "hda_codec: %s: "
1452 "Apply fix-verbs for %s\n",
1453 codec->chip_name, modelname);
1454 add_verb(codec->spec, fix->v.verbs);
1455 break;
1456 case ALC_FIXUP_FUNC:
1457 if (!fix->v.func)
1458 break;
1459 snd_printdd(KERN_INFO "hda_codec: %s: "
1460 "Apply fix-func for %s\n",
1461 codec->chip_name, modelname);
1462 fix->v.func(codec, fix, action);
1463 break;
1464 default:
1465 snd_printk(KERN_ERR "hda_codec: %s: "
1466 "Invalid fixup type %d\n",
1467 codec->chip_name, fix->type);
1468 break;
1469 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001470 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001471 break;
1472 if (++depth > 10)
1473 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001474 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001475 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001476}
1477
Todd Broche1eb5f12010-12-06 11:19:51 -08001478static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001479 const struct alc_model_fixup *models,
1480 const struct snd_pci_quirk *quirk,
1481 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001482{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001483 struct alc_spec *spec = codec->spec;
1484 int id = -1;
1485 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001486
Todd Broche1eb5f12010-12-06 11:19:51 -08001487 if (codec->modelname && models) {
1488 while (models->name) {
1489 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001490 id = models->id;
1491 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001492 break;
1493 }
1494 models++;
1495 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001496 }
1497 if (id < 0) {
1498 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1499 if (quirk) {
1500 id = quirk->value;
1501#ifdef CONFIG_SND_DEBUG_VERBOSE
1502 name = quirk->name;
1503#endif
1504 }
1505 }
1506
1507 spec->fixup_id = id;
1508 if (id >= 0) {
1509 spec->fixup_list = fixlist;
1510 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001511 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001512}
1513
Takashi Iwai1d045db2011-07-07 18:23:21 +02001514/*
1515 * COEF access helper functions
1516 */
Kailang Yang274693f2009-12-03 10:07:50 +01001517static int alc_read_coef_idx(struct hda_codec *codec,
1518 unsigned int coef_idx)
1519{
1520 unsigned int val;
1521 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1522 coef_idx);
1523 val = snd_hda_codec_read(codec, 0x20, 0,
1524 AC_VERB_GET_PROC_COEF, 0);
1525 return val;
1526}
1527
Kailang Yang977ddd62010-09-15 10:02:29 +02001528static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1529 unsigned int coef_val)
1530{
1531 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1532 coef_idx);
1533 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1534 coef_val);
1535}
1536
Takashi Iwai1d045db2011-07-07 18:23:21 +02001537/*
1538 * Digital I/O handling
1539 */
1540
Takashi Iwai757899a2010-07-30 10:48:14 +02001541/* set right pin controls for digital I/O */
1542static void alc_auto_init_digital(struct hda_codec *codec)
1543{
1544 struct alc_spec *spec = codec->spec;
1545 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001546 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001547
1548 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1549 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001550 if (!pin)
1551 continue;
1552 snd_hda_codec_write(codec, pin, 0,
1553 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1554 if (!i)
1555 dac = spec->multiout.dig_out_nid;
1556 else
1557 dac = spec->slave_dig_outs[i - 1];
1558 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1559 continue;
1560 snd_hda_codec_write(codec, dac, 0,
1561 AC_VERB_SET_AMP_GAIN_MUTE,
1562 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001563 }
1564 pin = spec->autocfg.dig_in_pin;
1565 if (pin)
1566 snd_hda_codec_write(codec, pin, 0,
1567 AC_VERB_SET_PIN_WIDGET_CONTROL,
1568 PIN_IN);
1569}
1570
1571/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1572static void alc_auto_parse_digital(struct hda_codec *codec)
1573{
1574 struct alc_spec *spec = codec->spec;
1575 int i, err;
1576 hda_nid_t dig_nid;
1577
1578 /* support multiple SPDIFs; the secondary is set up as a slave */
1579 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001580 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001581 err = snd_hda_get_connections(codec,
1582 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001583 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001584 if (err < 0)
1585 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001586 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001587 if (!i) {
1588 spec->multiout.dig_out_nid = dig_nid;
1589 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1590 } else {
1591 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1592 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1593 break;
1594 spec->slave_dig_outs[i - 1] = dig_nid;
1595 }
1596 }
1597
1598 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001599 dig_nid = codec->start_nid;
1600 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1601 unsigned int wcaps = get_wcaps(codec, dig_nid);
1602 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1603 continue;
1604 if (!(wcaps & AC_WCAP_DIGITAL))
1605 continue;
1606 if (!(wcaps & AC_WCAP_CONN_LIST))
1607 continue;
1608 err = get_connection_index(codec, dig_nid,
1609 spec->autocfg.dig_in_pin);
1610 if (err >= 0) {
1611 spec->dig_in_nid = dig_nid;
1612 break;
1613 }
1614 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001615 }
1616}
1617
Takashi Iwaif95474e2007-07-10 00:47:43 +02001618/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001619 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001620 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001621static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1622 struct snd_ctl_elem_info *uinfo)
1623{
1624 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1625 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001626 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001627 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001628
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001629 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001630 if (spec->vol_in_capsrc)
1631 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1632 else
1633 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1634 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001635 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001636 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001637 return err;
1638}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001640static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1641 unsigned int size, unsigned int __user *tlv)
1642{
1643 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1644 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001645 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001646 int err;
1647
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001648 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001649 if (spec->vol_in_capsrc)
1650 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1651 else
1652 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1653 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001654 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001655 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001656 return err;
1657}
1658
1659typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1660 struct snd_ctl_elem_value *ucontrol);
1661
1662static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1663 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001664 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001665{
1666 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1667 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001668 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001669
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001670 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001671 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001672 for (i = 0; i < spec->num_adc_nids; i++) {
1673 kcontrol->private_value =
1674 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1675 3, 0, HDA_INPUT);
1676 err = func(kcontrol, ucontrol);
1677 if (err < 0)
1678 goto error;
1679 }
1680 } else {
1681 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001682 if (spec->vol_in_capsrc)
1683 kcontrol->private_value =
1684 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1685 3, 0, HDA_OUTPUT);
1686 else
1687 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001688 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1689 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001690 err = func(kcontrol, ucontrol);
1691 }
1692 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001693 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001694 return err;
1695}
1696
1697static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1698 struct snd_ctl_elem_value *ucontrol)
1699{
1700 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001701 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001702}
1703
1704static int alc_cap_vol_put(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_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001709}
1710
1711/* capture mixer elements */
1712#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1713
1714static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1715 struct snd_ctl_elem_value *ucontrol)
1716{
1717 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001718 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001719}
1720
1721static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1722 struct snd_ctl_elem_value *ucontrol)
1723{
1724 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001725 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001726}
1727
Takashi Iwaia23b6882009-03-23 15:21:36 +01001728#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001729 { \
1730 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1731 .name = "Capture Switch", \
1732 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1733 .count = num, \
1734 .info = alc_cap_sw_info, \
1735 .get = alc_cap_sw_get, \
1736 .put = alc_cap_sw_put, \
1737 }, \
1738 { \
1739 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1740 .name = "Capture Volume", \
1741 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1742 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1743 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1744 .count = num, \
1745 .info = alc_cap_vol_info, \
1746 .get = alc_cap_vol_get, \
1747 .put = alc_cap_vol_put, \
1748 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001749 }
1750
1751#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001752 { \
1753 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1754 /* .name = "Capture Source", */ \
1755 .name = "Input Source", \
1756 .count = num, \
1757 .info = alc_mux_enum_info, \
1758 .get = alc_mux_enum_get, \
1759 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001760 }
1761
1762#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001763static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001764 _DEFINE_CAPMIX(num), \
1765 _DEFINE_CAPSRC(num), \
1766 { } /* end */ \
1767}
1768
1769#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001770static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001771 _DEFINE_CAPMIX(num), \
1772 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001773}
1774
1775/* up to three ADCs */
1776DEFINE_CAPMIX(1);
1777DEFINE_CAPMIX(2);
1778DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001779DEFINE_CAPMIX_NOSRC(1);
1780DEFINE_CAPMIX_NOSRC(2);
1781DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001782
1783/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001784 * virtual master controls
1785 */
1786
1787/*
1788 * slave controls for virtual master
1789 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001790static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001791 "Front Playback Volume",
1792 "Surround Playback Volume",
1793 "Center Playback Volume",
1794 "LFE Playback Volume",
1795 "Side Playback Volume",
1796 "Headphone Playback Volume",
1797 "Speaker Playback Volume",
1798 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001799 "Line-Out Playback Volume",
1800 NULL,
1801};
1802
Takashi Iwaiea734962011-01-17 11:29:34 +01001803static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001804 "Front Playback Switch",
1805 "Surround Playback Switch",
1806 "Center Playback Switch",
1807 "LFE Playback Switch",
1808 "Side Playback Switch",
1809 "Headphone Playback Switch",
1810 "Speaker Playback Switch",
1811 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001812 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001813 "Line-Out Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001814 NULL,
1815};
1816
1817/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001818 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001820
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001821#define NID_MAPPING (-1)
1822
1823#define SUBDEV_SPEAKER_ (0 << 6)
1824#define SUBDEV_HP_ (1 << 6)
1825#define SUBDEV_LINE_ (2 << 6)
1826#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1827#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1828#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1829
Takashi Iwai603c4012008-07-30 15:01:44 +02001830static void alc_free_kctls(struct hda_codec *codec);
1831
Takashi Iwai67d634c2009-11-16 15:35:59 +01001832#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001833/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001834static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001835 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001836 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001837 { } /* end */
1838};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001839#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001840
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841static int alc_build_controls(struct hda_codec *codec)
1842{
1843 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001844 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001845 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001846 int i, j, err;
1847 unsigned int u;
1848 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849
1850 for (i = 0; i < spec->num_mixers; i++) {
1851 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1852 if (err < 0)
1853 return err;
1854 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001855 if (spec->cap_mixer) {
1856 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1857 if (err < 0)
1858 return err;
1859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001861 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001862 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001863 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 if (err < 0)
1865 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001866 if (!spec->no_analog) {
1867 err = snd_hda_create_spdif_share_sw(codec,
1868 &spec->multiout);
1869 if (err < 0)
1870 return err;
1871 spec->multiout.share_spdif = 1;
1872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 }
1874 if (spec->dig_in_nid) {
1875 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1876 if (err < 0)
1877 return err;
1878 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001879
Takashi Iwai67d634c2009-11-16 15:35:59 +01001880#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001881 /* create beep controls if needed */
1882 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001883 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001884 for (knew = alc_beep_mixer; knew->name; knew++) {
1885 struct snd_kcontrol *kctl;
1886 kctl = snd_ctl_new1(knew, codec);
1887 if (!kctl)
1888 return -ENOMEM;
1889 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001890 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001891 if (err < 0)
1892 return err;
1893 }
1894 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001895#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001896
Takashi Iwai2134ea42008-01-10 16:53:55 +01001897 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001898 if (!spec->no_analog &&
1899 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001900 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001901 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001902 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001903 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001904 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001905 if (err < 0)
1906 return err;
1907 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001908 if (!spec->no_analog &&
1909 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001910 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1911 NULL, alc_slave_sws);
1912 if (err < 0)
1913 return err;
1914 }
1915
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001916 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001917 if (spec->capsrc_nids || spec->adc_nids) {
1918 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1919 if (!kctl)
1920 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1921 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001922 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001923 if (!nids)
1924 nids = spec->adc_nids;
1925 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1926 if (err < 0)
1927 return err;
1928 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001929 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001930 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001931 const char *kname = kctl ? kctl->id.name : NULL;
1932 for (knew = spec->cap_mixer; knew->name; knew++) {
1933 if (kname && strcmp(knew->name, kname) == 0)
1934 continue;
1935 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1936 for (i = 0; kctl && i < kctl->count; i++) {
1937 err = snd_hda_add_nid(codec, kctl, i,
1938 spec->adc_nids[i]);
1939 if (err < 0)
1940 return err;
1941 }
1942 }
1943 }
1944
1945 /* other nid->control mapping */
1946 for (i = 0; i < spec->num_mixers; i++) {
1947 for (knew = spec->mixers[i]; knew->name; knew++) {
1948 if (knew->iface != NID_MAPPING)
1949 continue;
1950 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1951 if (kctl == NULL)
1952 continue;
1953 u = knew->subdevice;
1954 for (j = 0; j < 4; j++, u >>= 8) {
1955 nid = u & 0x3f;
1956 if (nid == 0)
1957 continue;
1958 switch (u & 0xc0) {
1959 case SUBDEV_SPEAKER_:
1960 nid = spec->autocfg.speaker_pins[nid];
1961 break;
1962 case SUBDEV_LINE_:
1963 nid = spec->autocfg.line_out_pins[nid];
1964 break;
1965 case SUBDEV_HP_:
1966 nid = spec->autocfg.hp_pins[nid];
1967 break;
1968 default:
1969 continue;
1970 }
1971 err = snd_hda_add_nid(codec, kctl, 0, nid);
1972 if (err < 0)
1973 return err;
1974 }
1975 u = knew->private_value;
1976 for (j = 0; j < 4; j++, u >>= 8) {
1977 nid = u & 0xff;
1978 if (nid == 0)
1979 continue;
1980 err = snd_hda_add_nid(codec, kctl, 0, nid);
1981 if (err < 0)
1982 return err;
1983 }
1984 }
1985 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001986
1987 alc_free_kctls(codec); /* no longer needed */
1988
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 return 0;
1990}
1991
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001992
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001994 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001995 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001996
Takashi Iwai584c0c42011-03-10 12:51:11 +01001997static void alc_init_special_input_src(struct hda_codec *codec);
1998
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999static int alc_init(struct hda_codec *codec)
2000{
2001 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002002 unsigned int i;
2003
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002004 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02002005 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002006
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002007 for (i = 0; i < spec->num_init_verbs; i++)
2008 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01002009 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002010
2011 if (spec->init_hook)
2012 spec->init_hook(codec);
2013
Takashi Iwai58701122011-01-13 15:41:45 +01002014 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2015
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002016 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 return 0;
2018}
2019
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002020static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2021{
2022 struct alc_spec *spec = codec->spec;
2023
2024 if (spec->unsol_event)
2025 spec->unsol_event(codec, res);
2026}
2027
Takashi Iwaicb53c622007-08-10 17:21:45 +02002028#ifdef CONFIG_SND_HDA_POWER_SAVE
2029static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2030{
2031 struct alc_spec *spec = codec->spec;
2032 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2033}
2034#endif
2035
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036/*
2037 * Analog playback callbacks
2038 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002039static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002041 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042{
2043 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002044 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2045 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046}
2047
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002048static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 struct hda_codec *codec,
2050 unsigned int stream_tag,
2051 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002052 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053{
2054 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002055 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2056 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057}
2058
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002059static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002061 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062{
2063 struct alc_spec *spec = codec->spec;
2064 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2065}
2066
2067/*
2068 * Digital out
2069 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002070static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002072 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073{
2074 struct alc_spec *spec = codec->spec;
2075 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2076}
2077
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002078static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002079 struct hda_codec *codec,
2080 unsigned int stream_tag,
2081 unsigned int format,
2082 struct snd_pcm_substream *substream)
2083{
2084 struct alc_spec *spec = codec->spec;
2085 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2086 stream_tag, format, substream);
2087}
2088
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002089static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002090 struct hda_codec *codec,
2091 struct snd_pcm_substream *substream)
2092{
2093 struct alc_spec *spec = codec->spec;
2094 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2095}
2096
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002097static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002099 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100{
2101 struct alc_spec *spec = codec->spec;
2102 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2103}
2104
2105/*
2106 * Analog capture
2107 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002108static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 struct hda_codec *codec,
2110 unsigned int stream_tag,
2111 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002112 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113{
2114 struct alc_spec *spec = codec->spec;
2115
Takashi Iwai63300792008-01-24 15:31:36 +01002116 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 stream_tag, 0, format);
2118 return 0;
2119}
2120
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002121static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002123 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124{
2125 struct alc_spec *spec = codec->spec;
2126
Takashi Iwai888afa12008-03-18 09:57:50 +01002127 snd_hda_codec_cleanup_stream(codec,
2128 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 return 0;
2130}
2131
Takashi Iwai840b64c2010-07-13 22:49:01 +02002132/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002133static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002134 struct hda_codec *codec,
2135 unsigned int stream_tag,
2136 unsigned int format,
2137 struct snd_pcm_substream *substream)
2138{
2139 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002140 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002141 spec->cur_adc_stream_tag = stream_tag;
2142 spec->cur_adc_format = format;
2143 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2144 return 0;
2145}
2146
Takashi Iwai21268962011-07-07 15:01:13 +02002147static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002148 struct hda_codec *codec,
2149 struct snd_pcm_substream *substream)
2150{
2151 struct alc_spec *spec = codec->spec;
2152 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2153 spec->cur_adc = 0;
2154 return 0;
2155}
2156
Takashi Iwai21268962011-07-07 15:01:13 +02002157static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002158 .substreams = 1,
2159 .channels_min = 2,
2160 .channels_max = 2,
2161 .nid = 0, /* fill later */
2162 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002163 .prepare = dyn_adc_capture_pcm_prepare,
2164 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002165 },
2166};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167
2168/*
2169 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002170static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 .substreams = 1,
2172 .channels_min = 2,
2173 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002174 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002176 .open = alc_playback_pcm_open,
2177 .prepare = alc_playback_pcm_prepare,
2178 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 },
2180};
2181
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002182static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002183 .substreams = 1,
2184 .channels_min = 2,
2185 .channels_max = 2,
2186 /* NID is set in alc_build_pcms */
2187};
2188
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002189static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002190 .substreams = 1,
2191 .channels_min = 2,
2192 .channels_max = 2,
2193 /* NID is set in alc_build_pcms */
2194};
2195
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002196static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002197 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 .channels_min = 2,
2199 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002200 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002202 .prepare = alc_alt_capture_pcm_prepare,
2203 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 },
2205};
2206
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002207static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 .substreams = 1,
2209 .channels_min = 2,
2210 .channels_max = 2,
2211 /* NID is set in alc_build_pcms */
2212 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002213 .open = alc_dig_playback_pcm_open,
2214 .close = alc_dig_playback_pcm_close,
2215 .prepare = alc_dig_playback_pcm_prepare,
2216 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 },
2218};
2219
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002220static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 .substreams = 1,
2222 .channels_min = 2,
2223 .channels_max = 2,
2224 /* NID is set in alc_build_pcms */
2225};
2226
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002227/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002228static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002229 .substreams = 0,
2230 .channels_min = 0,
2231 .channels_max = 0,
2232};
2233
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234static int alc_build_pcms(struct hda_codec *codec)
2235{
2236 struct alc_spec *spec = codec->spec;
2237 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002238 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 int i;
2240
2241 codec->num_pcms = 1;
2242 codec->pcm_info = info;
2243
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002244 if (spec->no_analog)
2245 goto skip_analog;
2246
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002247 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2248 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002250
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002251 if (spec->multiout.dac_nids > 0) {
2252 p = spec->stream_analog_playback;
2253 if (!p)
2254 p = &alc_pcm_analog_playback;
2255 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002256 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2257 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002258 if (spec->adc_nids) {
2259 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002260 if (!p) {
2261 if (spec->dyn_adc_switch)
2262 p = &dyn_adc_pcm_analog_capture;
2263 else
2264 p = &alc_pcm_analog_capture;
2265 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002266 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002267 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269
Takashi Iwai4a471b72005-12-07 13:56:29 +01002270 if (spec->channel_mode) {
2271 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2272 for (i = 0; i < spec->num_channel_mode; i++) {
2273 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2274 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2275 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 }
2277 }
2278
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002279 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002280 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002282 snprintf(spec->stream_name_digital,
2283 sizeof(spec->stream_name_digital),
2284 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002285 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002286 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002287 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002289 if (spec->dig_out_type)
2290 info->pcm_type = spec->dig_out_type;
2291 else
2292 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002293 if (spec->multiout.dig_out_nid) {
2294 p = spec->stream_digital_playback;
2295 if (!p)
2296 p = &alc_pcm_digital_playback;
2297 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2299 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002300 if (spec->dig_in_nid) {
2301 p = spec->stream_digital_capture;
2302 if (!p)
2303 p = &alc_pcm_digital_capture;
2304 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2306 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002307 /* FIXME: do we need this for all Realtek codec models? */
2308 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 }
2310
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002311 if (spec->no_analog)
2312 return 0;
2313
Takashi Iwaie08a0072006-09-07 17:52:14 +02002314 /* If the use of more than one ADC is requested for the current
2315 * model, configure a second analog capture-only PCM.
2316 */
2317 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002318 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002319 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002320 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002321 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002322 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002323 p = spec->stream_analog_alt_playback;
2324 if (!p)
2325 p = &alc_pcm_analog_alt_playback;
2326 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002327 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2328 spec->alt_dac_nid;
2329 } else {
2330 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2331 alc_pcm_null_stream;
2332 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2333 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002334 if (spec->num_adc_nids > 1) {
2335 p = spec->stream_analog_alt_capture;
2336 if (!p)
2337 p = &alc_pcm_analog_alt_capture;
2338 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002339 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2340 spec->adc_nids[1];
2341 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2342 spec->num_adc_nids - 1;
2343 } else {
2344 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2345 alc_pcm_null_stream;
2346 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002347 }
2348 }
2349
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 return 0;
2351}
2352
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002353static inline void alc_shutup(struct hda_codec *codec)
2354{
Takashi Iwai1c716152011-04-07 10:37:16 +02002355 struct alc_spec *spec = codec->spec;
2356
2357 if (spec && spec->shutup)
2358 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002359 snd_hda_shutup_pins(codec);
2360}
2361
Takashi Iwai603c4012008-07-30 15:01:44 +02002362static void alc_free_kctls(struct hda_codec *codec)
2363{
2364 struct alc_spec *spec = codec->spec;
2365
2366 if (spec->kctls.list) {
2367 struct snd_kcontrol_new *kctl = spec->kctls.list;
2368 int i;
2369 for (i = 0; i < spec->kctls.used; i++)
2370 kfree(kctl[i].name);
2371 }
2372 snd_array_free(&spec->kctls);
2373}
2374
Takashi Iwai23c09b02011-08-19 09:05:35 +02002375static void alc_free_bind_ctls(struct hda_codec *codec)
2376{
2377 struct alc_spec *spec = codec->spec;
2378 if (spec->bind_ctls.list) {
2379 struct hda_bind_ctls **ctl = spec->bind_ctls.list;
2380 int i;
2381 for (i = 0; i < spec->bind_ctls.used; i++)
2382 kfree(ctl[i]);
2383 }
2384 snd_array_free(&spec->bind_ctls);
2385}
2386
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387static void alc_free(struct hda_codec *codec)
2388{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002389 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002390
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002391 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002392 return;
2393
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002394 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002395 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002396 alc_free_kctls(codec);
Takashi Iwai23c09b02011-08-19 09:05:35 +02002397 alc_free_bind_ctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002398 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002399 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400}
2401
Hector Martinf5de24b2009-12-20 22:51:31 +01002402#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002403static void alc_power_eapd(struct hda_codec *codec)
2404{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002405 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002406}
2407
Hector Martinf5de24b2009-12-20 22:51:31 +01002408static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2409{
2410 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002411 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002412 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002413 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002414 return 0;
2415}
2416#endif
2417
Takashi Iwai2a439522011-07-26 09:52:50 +02002418#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002419static int alc_resume(struct hda_codec *codec)
2420{
Takashi Iwai1c716152011-04-07 10:37:16 +02002421 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002422 codec->patch_ops.init(codec);
2423 snd_hda_codec_resume_amp(codec);
2424 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002425 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002426 return 0;
2427}
Takashi Iwaie044c392008-10-27 16:56:24 +01002428#endif
2429
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430/*
2431 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002432static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 .build_controls = alc_build_controls,
2434 .build_pcms = alc_build_pcms,
2435 .init = alc_init,
2436 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002437 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002438#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002439 .resume = alc_resume,
2440#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002441#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002442 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002443 .check_power_status = alc_check_power_status,
2444#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002445 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446};
2447
Kailang Yangc027ddc2010-03-19 11:33:06 +01002448/* replace the codec chip_name with the given string */
2449static int alc_codec_rename(struct hda_codec *codec, const char *name)
2450{
2451 kfree(codec->chip_name);
2452 codec->chip_name = kstrdup(name, GFP_KERNEL);
2453 if (!codec->chip_name) {
2454 alc_free(codec);
2455 return -ENOMEM;
2456 }
2457 return 0;
2458}
2459
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002460/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002461 * Automatic parse of I/O pins from the BIOS configuration
2462 */
2463
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002464enum {
2465 ALC_CTL_WIDGET_VOL,
2466 ALC_CTL_WIDGET_MUTE,
2467 ALC_CTL_BIND_MUTE,
Takashi Iwai23c09b02011-08-19 09:05:35 +02002468 ALC_CTL_BIND_VOL,
2469 ALC_CTL_BIND_SW,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002470};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002471static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002472 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2473 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002474 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwai23c09b02011-08-19 09:05:35 +02002475 HDA_BIND_VOL(NULL, 0),
2476 HDA_BIND_SW(NULL, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002477};
2478
2479/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002480static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002481 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002482{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002483 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002484
Takashi Iwaice764ab2011-04-27 16:35:23 +02002485 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002486 if (!knew)
2487 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002488 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002489 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002490 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002491 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002492 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002493 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002494 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002495 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002496 return 0;
2497}
2498
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002499static int add_control_with_pfx(struct alc_spec *spec, int type,
2500 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002501 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002502{
2503 char name[32];
2504 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002505 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002506}
2507
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002508#define add_pb_vol_ctrl(spec, type, pfx, val) \
2509 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2510#define add_pb_sw_ctrl(spec, type, pfx, val) \
2511 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2512#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2513 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2514#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2515 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002516
Takashi Iwai23c09b02011-08-19 09:05:35 +02002517static const char * const channel_name[4] = {
2518 "Front", "Surround", "CLFE", "Side"
2519};
2520
Takashi Iwai6843ca12011-06-24 11:03:58 +02002521static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2522 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002523{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002524 struct auto_pin_cfg *cfg = &spec->autocfg;
2525
Takashi Iwai6843ca12011-06-24 11:03:58 +02002526 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002527 if (cfg->line_outs == 1 && !spec->multi_ios &&
2528 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002529 return "Master";
2530
2531 switch (cfg->line_out_type) {
2532 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002533 if (cfg->line_outs == 1)
2534 return "Speaker";
2535 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002536 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002537 /* for multi-io case, only the primary out */
2538 if (ch && spec->multi_ios)
2539 break;
2540 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002541 return "Headphone";
2542 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002543 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002544 return "PCM";
2545 break;
2546 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02002547 if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name)))
2548 return "PCM";
2549
2550 return channel_name[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002551}
2552
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002553/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002554static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002555 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002556 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002557{
Kailang Yangdf694da2005-12-05 19:42:22 +01002558 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002559
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002560 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002561 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2562 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002563 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002564 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002565 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2566 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002567 return err;
2568 return 0;
2569}
2570
Takashi Iwai05f5f472009-08-25 13:10:18 +02002571static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002572{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002573 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2574 return (pincap & AC_PINCAP_IN) != 0;
2575}
2576
Takashi Iwai1d045db2011-07-07 18:23:21 +02002577/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002578static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002579{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002580 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002581 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002582 hda_nid_t *adc_nids = spec->private_adc_nids;
2583 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2584 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2585 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002586 int i, nums = 0;
2587
2588 nid = codec->start_nid;
2589 for (i = 0; i < codec->num_nodes; i++, nid++) {
2590 hda_nid_t src;
2591 const hda_nid_t *list;
2592 unsigned int caps = get_wcaps(codec, nid);
2593 int type = get_wcaps_type(caps);
2594
2595 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2596 continue;
2597 adc_nids[nums] = nid;
2598 cap_nids[nums] = nid;
2599 src = nid;
2600 for (;;) {
2601 int n;
2602 type = get_wcaps_type(get_wcaps(codec, src));
2603 if (type == AC_WID_PIN)
2604 break;
2605 if (type == AC_WID_AUD_SEL) {
2606 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002607 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002608 break;
2609 }
2610 n = snd_hda_get_conn_list(codec, src, &list);
2611 if (n > 1) {
2612 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002613 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002614 break;
2615 } else if (n != 1)
2616 break;
2617 src = *list;
2618 }
2619 if (++nums >= max_nums)
2620 break;
2621 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002622 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002623 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002624 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002625 return nums;
2626}
2627
Takashi Iwai05f5f472009-08-25 13:10:18 +02002628/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002629static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002630{
2631 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002632 const struct auto_pin_cfg *cfg = &spec->autocfg;
2633 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002634 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002635 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002636 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002637 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002638
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002639 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002640 if (num_adcs < 0)
2641 return 0;
2642
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002643 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002644 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002645 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002646
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002647 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002648 if (!alc_is_input_pin(codec, pin))
2649 continue;
2650
David Henningsson5322bf22011-01-05 11:03:56 +01002651 label = hda_get_autocfg_input_label(codec, cfg, i);
2652 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002653 type_idx++;
2654 else
2655 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002656 prev_label = label;
2657
Takashi Iwai05f5f472009-08-25 13:10:18 +02002658 if (mixer) {
2659 idx = get_connection_index(codec, mixer, pin);
2660 if (idx >= 0) {
2661 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002662 label, type_idx,
2663 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002664 if (err < 0)
2665 return err;
2666 }
2667 }
2668
Takashi Iwaib7821702011-07-06 15:12:46 +02002669 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002670 hda_nid_t cap = spec->capsrc_nids ?
2671 spec->capsrc_nids[c] : spec->adc_nids[c];
2672 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002673 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002674 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002675 snd_hda_add_imux_item(imux, label, idx, NULL);
2676 break;
2677 }
2678 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002679 }
Takashi Iwai21268962011-07-07 15:01:13 +02002680
2681 spec->num_mux_defs = 1;
2682 spec->input_mux = imux;
2683
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002684 return 0;
2685}
2686
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002687static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2688 unsigned int pin_type)
2689{
2690 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2691 pin_type);
2692 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002693 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2694 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002695 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002696}
2697
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002698static int get_pin_type(int line_out_type)
2699{
2700 if (line_out_type == AUTO_PIN_HP_OUT)
2701 return PIN_HP;
2702 else
2703 return PIN_OUT;
2704}
2705
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002706static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002707{
2708 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002709 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002710 int i;
2711
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002712 for (i = 0; i < cfg->num_inputs; i++) {
2713 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002714 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002715 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002716 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002717 snd_hda_codec_write(codec, nid, 0,
2718 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002719 AMP_OUT_MUTE);
2720 }
2721 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002722
2723 /* mute all loopback inputs */
2724 if (spec->mixer_nid) {
2725 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2726 for (i = 0; i < nums; i++)
2727 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2728 AC_VERB_SET_AMP_GAIN_MUTE,
2729 AMP_IN_MUTE(i));
2730 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002731}
2732
Takashi Iwai7085ec12009-10-02 09:03:58 +02002733/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002734static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002735{
Takashi Iwai604401a2011-04-27 15:14:23 +02002736 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002737 int i, num;
2738
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002739 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2740 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002741 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2742 for (i = 0; i < num; i++) {
2743 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2744 return list[i];
2745 }
2746 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002747}
2748
Takashi Iwai604401a2011-04-27 15:14:23 +02002749/* go down to the selector widget before the mixer */
2750static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2751{
2752 hda_nid_t srcs[5];
2753 int num = snd_hda_get_connections(codec, pin, srcs,
2754 ARRAY_SIZE(srcs));
2755 if (num != 1 ||
2756 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2757 return pin;
2758 return srcs[0];
2759}
2760
Takashi Iwai7085ec12009-10-02 09:03:58 +02002761/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002762static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002763 hda_nid_t dac)
2764{
David Henningssoncc1c4522010-11-24 14:17:47 +01002765 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002766 int i, num;
2767
Takashi Iwai604401a2011-04-27 15:14:23 +02002768 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002769 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2770 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002771 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002772 return mix[i];
2773 }
2774 return 0;
2775}
2776
Takashi Iwaice764ab2011-04-27 16:35:23 +02002777/* select the connection from pin to DAC if needed */
2778static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2779 hda_nid_t dac)
2780{
2781 hda_nid_t mix[5];
2782 int i, num;
2783
2784 pin = alc_go_down_to_selector(codec, pin);
2785 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2786 if (num < 2)
2787 return 0;
2788 for (i = 0; i < num; i++) {
2789 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2790 snd_hda_codec_update_cache(codec, pin, 0,
2791 AC_VERB_SET_CONNECT_SEL, i);
2792 return 0;
2793 }
2794 }
2795 return 0;
2796}
2797
Takashi Iwai7085ec12009-10-02 09:03:58 +02002798/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002799static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002800{
2801 struct alc_spec *spec = codec->spec;
2802 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002803 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002804
Takashi Iwai604401a2011-04-27 15:14:23 +02002805 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002806 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002807 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002808 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002809 if (!nid)
2810 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002811 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2812 spec->multiout.num_dacs))
2813 continue;
2814 if (spec->multiout.hp_nid == nid)
2815 continue;
2816 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2817 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2818 continue;
2819 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002820 }
2821 return 0;
2822}
2823
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002824static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2825{
2826 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2827 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2828 return alc_auto_look_for_dac(codec, pin);
2829 return 0;
2830}
2831
Takashi Iwai7085ec12009-10-02 09:03:58 +02002832/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002833static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002834{
2835 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002836 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002837 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002838 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002839
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002840 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002841 /* set num_dacs once to full for alc_auto_look_for_dac() */
2842 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002843 spec->multiout.hp_nid = 0;
2844 spec->multiout.extra_out_nid[0] = 0;
2845 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2846 spec->multiout.dac_nids = spec->private_dac_nids;
2847
2848 /* fill hard-wired DACs first */
2849 if (!redone) {
2850 for (i = 0; i < cfg->line_outs; i++)
2851 spec->private_dac_nids[i] =
2852 get_dac_if_single(codec, cfg->line_out_pins[i]);
2853 if (cfg->hp_outs)
2854 spec->multiout.hp_nid =
2855 get_dac_if_single(codec, cfg->hp_pins[0]);
2856 if (cfg->speaker_outs)
2857 spec->multiout.extra_out_nid[0] =
2858 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002859 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002860
2861 for (i = 0; i < cfg->line_outs; i++) {
2862 hda_nid_t pin = cfg->line_out_pins[i];
2863 if (spec->private_dac_nids[i])
2864 continue;
2865 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2866 if (!spec->private_dac_nids[i] && !redone) {
2867 /* if we can't find primary DACs, re-probe without
2868 * checking the hard-wired DACs
2869 */
2870 redone = true;
2871 goto again;
2872 }
2873 }
2874
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002875 /* re-count num_dacs and squash invalid entries */
2876 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002877 for (i = 0; i < cfg->line_outs; i++) {
2878 if (spec->private_dac_nids[i])
2879 spec->multiout.num_dacs++;
2880 else
2881 memmove(spec->private_dac_nids + i,
2882 spec->private_dac_nids + i + 1,
2883 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2884 }
2885
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002886 if (cfg->hp_outs && !spec->multiout.hp_nid)
2887 spec->multiout.hp_nid =
2888 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2889 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2890 spec->multiout.extra_out_nid[0] =
2891 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2892
Takashi Iwai7085ec12009-10-02 09:03:58 +02002893 return 0;
2894}
2895
Takashi Iwai23c09b02011-08-19 09:05:35 +02002896/* fill in the dac_nids table for surround speakers, etc */
2897static int alc_auto_fill_extra_dacs(struct hda_codec *codec)
2898{
2899 struct alc_spec *spec = codec->spec;
2900 const struct auto_pin_cfg *cfg = &spec->autocfg;
2901 int i;
2902
2903 if (cfg->speaker_outs < 2 || !spec->multiout.extra_out_nid[0])
2904 return 0;
2905
2906 for (i = 1; i < cfg->speaker_outs; i++)
2907 spec->multiout.extra_out_nid[i] =
2908 get_dac_if_single(codec, cfg->speaker_pins[i]);
2909 for (i = 1; i < cfg->speaker_outs; i++) {
2910 if (spec->multiout.extra_out_nid[i])
2911 continue;
2912 spec->multiout.extra_out_nid[i] =
2913 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2914 }
2915 return 0;
2916}
2917
Takashi Iwai343a04b2011-07-06 14:28:39 +02002918static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002919 const char *pfx, int cidx,
2920 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002921{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002922 if (!nid)
2923 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002924 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2925 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002926}
2927
Takashi Iwai343a04b2011-07-06 14:28:39 +02002928#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2929 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002930
2931/* create a mute-switch for the given mixer widget;
2932 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2933 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002934static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002935 const char *pfx, int cidx,
2936 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002937{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002938 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002939 int type;
2940 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002941 if (!nid)
2942 return 0;
2943 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2944 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2945 type = ALC_CTL_WIDGET_MUTE;
2946 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2947 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002948 type = ALC_CTL_WIDGET_MUTE;
2949 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2950 } else {
2951 type = ALC_CTL_BIND_MUTE;
2952 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2953 }
2954 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002955}
2956
Takashi Iwai343a04b2011-07-06 14:28:39 +02002957#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2958 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002959
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002960static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2961 hda_nid_t pin, hda_nid_t dac)
2962{
2963 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2964 if (nid_has_mute(codec, pin, HDA_OUTPUT))
2965 return pin;
2966 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
2967 return mix;
2968 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
2969 return dac;
2970 return 0;
2971}
2972
2973static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
2974 hda_nid_t pin, hda_nid_t dac)
2975{
2976 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2977 if (nid_has_volume(codec, dac, HDA_OUTPUT))
2978 return dac;
2979 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
2980 return mix;
2981 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
2982 return pin;
2983 return 0;
2984}
2985
Takashi Iwai7085ec12009-10-02 09:03:58 +02002986/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002987static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002988 const struct auto_pin_cfg *cfg)
2989{
2990 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002991 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002992
Takashi Iwaice764ab2011-04-27 16:35:23 +02002993 noutputs = cfg->line_outs;
2994 if (spec->multi_ios > 0)
2995 noutputs += spec->multi_ios;
2996
2997 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002998 const char *name;
2999 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003000 hda_nid_t dac, pin;
3001 hda_nid_t sw, vol;
3002
3003 dac = spec->multiout.dac_nids[i];
3004 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003005 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003006 if (i >= cfg->line_outs)
3007 pin = spec->multi_io[i - 1].pin;
3008 else
3009 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003010
3011 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3012 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02003013 name = alc_get_line_out_pfx(spec, i, true, &index);
3014 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003015 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003016 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003017 if (err < 0)
3018 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003019 err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003020 if (err < 0)
3021 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003022 err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003023 if (err < 0)
3024 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003025 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003026 if (err < 0)
3027 return err;
3028 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003029 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003030 if (err < 0)
3031 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003032 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003033 if (err < 0)
3034 return err;
3035 }
3036 }
3037 return 0;
3038}
3039
Takashi Iwai343a04b2011-07-06 14:28:39 +02003040static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai23c09b02011-08-19 09:05:35 +02003041 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003042{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003043 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003044 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003045 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003046
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003047 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02003048 /* the corresponding DAC is already occupied */
3049 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
3050 return 0; /* no way */
3051 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02003052 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003053 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3054 }
3055
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003056 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3057 vol = alc_look_for_out_vol_nid(codec, pin, dac);
3058 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003059 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003060 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003061 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003062 if (err < 0)
3063 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003064 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003065}
3066
Takashi Iwai23c09b02011-08-19 09:05:35 +02003067static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
3068 unsigned int nums,
3069 struct hda_ctl_ops *ops)
3070{
3071 struct alc_spec *spec = codec->spec;
3072 struct hda_bind_ctls **ctlp, *ctl;
3073 snd_array_init(&spec->bind_ctls, sizeof(ctl), 8);
3074 ctlp = snd_array_new(&spec->bind_ctls);
3075 if (!ctlp)
3076 return NULL;
3077 ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL);
3078 *ctlp = ctl;
3079 if (ctl)
3080 ctl->ops = ops;
3081 return ctl;
3082}
3083
3084/* add playback controls for speaker and HP outputs */
3085static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
3086 const hda_nid_t *pins,
3087 const hda_nid_t *dacs,
3088 const char *pfx)
3089{
3090 struct alc_spec *spec = codec->spec;
3091 struct hda_bind_ctls *ctl;
3092 char name[32];
3093 int i, n, err;
3094
3095 if (!num_pins || !pins[0])
3096 return 0;
3097
3098 if (num_pins == 1)
3099 return alc_auto_create_extra_out(codec, *pins, *dacs, pfx);
3100
3101 if (dacs[num_pins - 1]) {
3102 /* OK, we have a multi-output system with individual volumes */
3103 for (i = 0; i < num_pins; i++) {
3104 snprintf(name, sizeof(name), "%s %s",
3105 pfx, channel_name[i]);
3106 err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
3107 name);
3108 if (err < 0)
3109 return err;
3110 }
3111 return 0;
3112 }
3113
3114 /* Let's create a bind-controls */
3115 ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw);
3116 if (!ctl)
3117 return -ENOMEM;
3118 n = 0;
3119 for (i = 0; i < num_pins; i++) {
3120 if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP)
3121 ctl->values[n++] =
3122 HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT);
3123 }
3124 if (n) {
3125 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
3126 err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl);
3127 if (err < 0)
3128 return err;
3129 }
3130
3131 ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
3132 if (!ctl)
3133 return -ENOMEM;
3134 n = 0;
3135 for (i = 0; i < num_pins; i++) {
3136 hda_nid_t vol;
3137 if (!pins[i] || !dacs[i])
3138 continue;
3139 vol = alc_look_for_out_vol_nid(codec, pins[i], dacs[i]);
3140 if (vol)
3141 ctl->values[n++] =
3142 HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT);
3143 }
3144 if (n) {
3145 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
3146 err = add_control(spec, ALC_CTL_BIND_VOL, name, 0, (long)ctl);
3147 if (err < 0)
3148 return err;
3149 }
3150 return 0;
3151}
3152
Takashi Iwai343a04b2011-07-06 14:28:39 +02003153static int alc_auto_create_hp_out(struct hda_codec *codec)
3154{
3155 struct alc_spec *spec = codec->spec;
3156 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3157 spec->multiout.hp_nid,
3158 "Headphone");
3159}
3160
3161static int alc_auto_create_speaker_out(struct hda_codec *codec)
3162{
3163 struct alc_spec *spec = codec->spec;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003164 return alc_auto_create_extra_outs(codec, spec->autocfg.speaker_outs,
3165 spec->autocfg.speaker_pins,
3166 spec->multiout.extra_out_nid,
3167 "Speaker");
Takashi Iwai343a04b2011-07-06 14:28:39 +02003168}
3169
Takashi Iwai343a04b2011-07-06 14:28:39 +02003170static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003171 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003172 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003173{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003174 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003175 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003176 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003177
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003178 alc_set_pin_output(codec, pin, pin_type);
3179 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003180 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003181 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003182 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003183 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003184 mix = srcs[i];
3185 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003186 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003187 if (!mix)
3188 return;
3189
3190 /* need the manual connection? */
3191 if (num > 1)
3192 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3193 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003194 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3195 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003196 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003197 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003198 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003199 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003200 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003201 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3202 if (nid)
3203 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3204 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003205}
3206
Takashi Iwai343a04b2011-07-06 14:28:39 +02003207static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003208{
3209 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003210 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003211 int i;
3212
3213 for (i = 0; i <= HDA_SIDE; i++) {
3214 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3215 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003216 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003217 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003218 }
3219}
3220
Takashi Iwai343a04b2011-07-06 14:28:39 +02003221static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003222{
3223 struct alc_spec *spec = codec->spec;
3224 hda_nid_t pin;
3225
3226 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003227 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003228 alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003229 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003230 pin = spec->autocfg.speaker_pins[0];
3231 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003232 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003233 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003234}
3235
Takashi Iwaice764ab2011-04-27 16:35:23 +02003236/*
3237 * multi-io helper
3238 */
3239static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3240 unsigned int location)
3241{
3242 struct alc_spec *spec = codec->spec;
3243 struct auto_pin_cfg *cfg = &spec->autocfg;
3244 int type, i, num_pins = 0;
3245
3246 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3247 for (i = 0; i < cfg->num_inputs; i++) {
3248 hda_nid_t nid = cfg->inputs[i].pin;
3249 hda_nid_t dac;
3250 unsigned int defcfg, caps;
3251 if (cfg->inputs[i].type != type)
3252 continue;
3253 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3254 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3255 continue;
3256 if (location && get_defcfg_location(defcfg) != location)
3257 continue;
3258 caps = snd_hda_query_pin_caps(codec, nid);
3259 if (!(caps & AC_PINCAP_OUT))
3260 continue;
3261 dac = alc_auto_look_for_dac(codec, nid);
3262 if (!dac)
3263 continue;
3264 spec->multi_io[num_pins].pin = nid;
3265 spec->multi_io[num_pins].dac = dac;
3266 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003267 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003268 }
3269 }
3270 spec->multiout.num_dacs = 1;
3271 if (num_pins < 2)
3272 return 0;
3273 return num_pins;
3274}
3275
3276static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3277 struct snd_ctl_elem_info *uinfo)
3278{
3279 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3280 struct alc_spec *spec = codec->spec;
3281
3282 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3283 uinfo->count = 1;
3284 uinfo->value.enumerated.items = spec->multi_ios + 1;
3285 if (uinfo->value.enumerated.item > spec->multi_ios)
3286 uinfo->value.enumerated.item = spec->multi_ios;
3287 sprintf(uinfo->value.enumerated.name, "%dch",
3288 (uinfo->value.enumerated.item + 1) * 2);
3289 return 0;
3290}
3291
3292static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3293 struct snd_ctl_elem_value *ucontrol)
3294{
3295 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3296 struct alc_spec *spec = codec->spec;
3297 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3298 return 0;
3299}
3300
3301static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3302{
3303 struct alc_spec *spec = codec->spec;
3304 hda_nid_t nid = spec->multi_io[idx].pin;
3305
3306 if (!spec->multi_io[idx].ctl_in)
3307 spec->multi_io[idx].ctl_in =
3308 snd_hda_codec_read(codec, nid, 0,
3309 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3310 if (output) {
3311 snd_hda_codec_update_cache(codec, nid, 0,
3312 AC_VERB_SET_PIN_WIDGET_CONTROL,
3313 PIN_OUT);
3314 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3315 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3316 HDA_AMP_MUTE, 0);
3317 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3318 } else {
3319 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3320 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3321 HDA_AMP_MUTE, HDA_AMP_MUTE);
3322 snd_hda_codec_update_cache(codec, nid, 0,
3323 AC_VERB_SET_PIN_WIDGET_CONTROL,
3324 spec->multi_io[idx].ctl_in);
3325 }
3326 return 0;
3327}
3328
3329static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3330 struct snd_ctl_elem_value *ucontrol)
3331{
3332 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3333 struct alc_spec *spec = codec->spec;
3334 int i, ch;
3335
3336 ch = ucontrol->value.enumerated.item[0];
3337 if (ch < 0 || ch > spec->multi_ios)
3338 return -EINVAL;
3339 if (ch == (spec->ext_channel_count - 1) / 2)
3340 return 0;
3341 spec->ext_channel_count = (ch + 1) * 2;
3342 for (i = 0; i < spec->multi_ios; i++)
3343 alc_set_multi_io(codec, i, i < ch);
3344 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003345 if (spec->need_dac_fix && !spec->const_channel_count)
3346 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003347 return 1;
3348}
3349
Takashi Iwaia9111322011-05-02 11:30:18 +02003350static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003351 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3352 .name = "Channel Mode",
3353 .info = alc_auto_ch_mode_info,
3354 .get = alc_auto_ch_mode_get,
3355 .put = alc_auto_ch_mode_put,
3356};
3357
Takashi Iwai23c09b02011-08-19 09:05:35 +02003358static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003359{
3360 struct alc_spec *spec = codec->spec;
3361 struct auto_pin_cfg *cfg = &spec->autocfg;
3362 unsigned int location, defcfg;
3363 int num_pins;
3364
3365 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003366 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003367 return 0;
3368
3369 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3370 location = get_defcfg_location(defcfg);
3371
3372 num_pins = alc_auto_fill_multi_ios(codec, location);
3373 if (num_pins > 0) {
3374 struct snd_kcontrol_new *knew;
3375
3376 knew = alc_kcontrol_new(spec);
3377 if (!knew)
3378 return -ENOMEM;
3379 *knew = alc_auto_channel_mode_enum;
3380 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3381 if (!knew->name)
3382 return -ENOMEM;
3383
3384 spec->multi_ios = num_pins;
3385 spec->ext_channel_count = 2;
3386 spec->multiout.num_dacs = num_pins + 1;
3387 }
3388 return 0;
3389}
3390
Takashi Iwai1d045db2011-07-07 18:23:21 +02003391/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3392 * active input pins
3393 */
3394static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3395{
3396 struct alc_spec *spec = codec->spec;
3397 const struct hda_input_mux *imux;
3398 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3399 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3400 int i, n, nums;
3401
3402 imux = spec->input_mux;
3403 if (!imux)
3404 return;
3405 if (spec->dyn_adc_switch)
3406 return;
3407
3408 nums = 0;
3409 for (n = 0; n < spec->num_adc_nids; n++) {
3410 hda_nid_t cap = spec->private_capsrc_nids[n];
3411 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3412 for (i = 0; i < imux->num_items; i++) {
3413 hda_nid_t pin = spec->imux_pins[i];
3414 if (pin) {
3415 if (get_connection_index(codec, cap, pin) < 0)
3416 break;
3417 } else if (num_conns <= imux->items[i].index)
3418 break;
3419 }
3420 if (i >= imux->num_items) {
3421 adc_nids[nums] = spec->private_adc_nids[n];
3422 capsrc_nids[nums++] = cap;
3423 }
3424 }
3425 if (!nums) {
3426 /* check whether ADC-switch is possible */
3427 if (!alc_check_dyn_adc_switch(codec)) {
3428 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3429 " using fallback 0x%x\n",
3430 codec->chip_name, spec->private_adc_nids[0]);
3431 spec->num_adc_nids = 1;
3432 spec->auto_mic = 0;
3433 return;
3434 }
3435 } else if (nums != spec->num_adc_nids) {
3436 memcpy(spec->private_adc_nids, adc_nids,
3437 nums * sizeof(hda_nid_t));
3438 memcpy(spec->private_capsrc_nids, capsrc_nids,
3439 nums * sizeof(hda_nid_t));
3440 spec->num_adc_nids = nums;
3441 }
3442
3443 if (spec->auto_mic)
3444 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3445 else if (spec->input_mux->num_items == 1)
3446 spec->num_adc_nids = 1; /* reduce to a single ADC */
3447}
3448
3449/*
3450 * initialize ADC paths
3451 */
3452static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3453{
3454 struct alc_spec *spec = codec->spec;
3455 hda_nid_t nid;
3456
3457 nid = spec->adc_nids[adc_idx];
3458 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003459 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003460 snd_hda_codec_write(codec, nid, 0,
3461 AC_VERB_SET_AMP_GAIN_MUTE,
3462 AMP_IN_MUTE(0));
3463 return;
3464 }
3465 if (!spec->capsrc_nids)
3466 return;
3467 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003468 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003469 snd_hda_codec_write(codec, nid, 0,
3470 AC_VERB_SET_AMP_GAIN_MUTE,
3471 AMP_OUT_MUTE);
3472}
3473
3474static void alc_auto_init_input_src(struct hda_codec *codec)
3475{
3476 struct alc_spec *spec = codec->spec;
3477 int c, nums;
3478
3479 for (c = 0; c < spec->num_adc_nids; c++)
3480 alc_auto_init_adc(codec, c);
3481 if (spec->dyn_adc_switch)
3482 nums = 1;
3483 else
3484 nums = spec->num_adc_nids;
3485 for (c = 0; c < nums; c++)
3486 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3487}
3488
3489/* add mic boosts if needed */
3490static int alc_auto_add_mic_boost(struct hda_codec *codec)
3491{
3492 struct alc_spec *spec = codec->spec;
3493 struct auto_pin_cfg *cfg = &spec->autocfg;
3494 int i, err;
3495 int type_idx = 0;
3496 hda_nid_t nid;
3497 const char *prev_label = NULL;
3498
3499 for (i = 0; i < cfg->num_inputs; i++) {
3500 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3501 break;
3502 nid = cfg->inputs[i].pin;
3503 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3504 const char *label;
3505 char boost_label[32];
3506
3507 label = hda_get_autocfg_input_label(codec, cfg, i);
3508 if (prev_label && !strcmp(label, prev_label))
3509 type_idx++;
3510 else
3511 type_idx = 0;
3512 prev_label = label;
3513
3514 snprintf(boost_label, sizeof(boost_label),
3515 "%s Boost Volume", label);
3516 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3517 boost_label, type_idx,
3518 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3519 if (err < 0)
3520 return err;
3521 }
3522 }
3523 return 0;
3524}
3525
3526/* select or unmute the given capsrc route */
3527static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3528 int idx)
3529{
3530 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3531 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3532 HDA_AMP_MUTE, 0);
3533 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3534 snd_hda_codec_write_cache(codec, cap, 0,
3535 AC_VERB_SET_CONNECT_SEL, idx);
3536 }
3537}
3538
3539/* set the default connection to that pin */
3540static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3541{
3542 struct alc_spec *spec = codec->spec;
3543 int i;
3544
3545 if (!pin)
3546 return 0;
3547 for (i = 0; i < spec->num_adc_nids; i++) {
3548 hda_nid_t cap = spec->capsrc_nids ?
3549 spec->capsrc_nids[i] : spec->adc_nids[i];
3550 int idx;
3551
3552 idx = get_connection_index(codec, cap, pin);
3553 if (idx < 0)
3554 continue;
3555 select_or_unmute_capsrc(codec, cap, idx);
3556 return i; /* return the found index */
3557 }
3558 return -1; /* not found */
3559}
3560
3561/* initialize some special cases for input sources */
3562static void alc_init_special_input_src(struct hda_codec *codec)
3563{
3564 struct alc_spec *spec = codec->spec;
3565 int i;
3566
3567 for (i = 0; i < spec->autocfg.num_inputs; i++)
3568 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3569}
3570
3571/* assign appropriate capture mixers */
3572static void set_capture_mixer(struct hda_codec *codec)
3573{
3574 struct alc_spec *spec = codec->spec;
3575 static const struct snd_kcontrol_new *caps[2][3] = {
3576 { alc_capture_mixer_nosrc1,
3577 alc_capture_mixer_nosrc2,
3578 alc_capture_mixer_nosrc3 },
3579 { alc_capture_mixer1,
3580 alc_capture_mixer2,
3581 alc_capture_mixer3 },
3582 };
3583
3584 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003585 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003586 if (!spec->capsrc_nids)
3587 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003588 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003589 return; /* no volume in capsrc, too */
3590 spec->vol_in_capsrc = 1;
3591 }
3592
3593 if (spec->num_adc_nids > 0) {
3594 int mux = 0;
3595 int num_adcs = 0;
3596
3597 if (spec->input_mux && spec->input_mux->num_items > 1)
3598 mux = 1;
3599 if (spec->auto_mic) {
3600 num_adcs = 1;
3601 mux = 0;
3602 } else if (spec->dyn_adc_switch)
3603 num_adcs = 1;
3604 if (!num_adcs) {
3605 if (spec->num_adc_nids > 3)
3606 spec->num_adc_nids = 3;
3607 else if (!spec->num_adc_nids)
3608 return;
3609 num_adcs = spec->num_adc_nids;
3610 }
3611 spec->cap_mixer = caps[mux][num_adcs - 1];
3612 }
3613}
3614
3615/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003616 * standard auto-parser initializations
3617 */
3618static void alc_auto_init_std(struct hda_codec *codec)
3619{
3620 struct alc_spec *spec = codec->spec;
3621 alc_auto_init_multi_out(codec);
3622 alc_auto_init_extra_out(codec);
3623 alc_auto_init_analog_input(codec);
3624 alc_auto_init_input_src(codec);
3625 alc_auto_init_digital(codec);
3626 if (spec->unsol_event)
3627 alc_inithook(codec);
3628}
3629
3630/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003631 * Digital-beep handlers
3632 */
3633#ifdef CONFIG_SND_HDA_INPUT_BEEP
3634#define set_beep_amp(spec, nid, idx, dir) \
3635 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3636
3637static const struct snd_pci_quirk beep_white_list[] = {
3638 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3639 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3640 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3641 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3642 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3643 {}
3644};
3645
3646static inline int has_cdefine_beep(struct hda_codec *codec)
3647{
3648 struct alc_spec *spec = codec->spec;
3649 const struct snd_pci_quirk *q;
3650 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3651 if (q)
3652 return q->value;
3653 return spec->cdefine.enable_pcbeep;
3654}
3655#else
3656#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3657#define has_cdefine_beep(codec) 0
3658#endif
3659
3660/* parse the BIOS configuration and set up the alc_spec */
3661/* return 1 if successful, 0 if the proper config is not found,
3662 * or a negative error code
3663 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003664static int alc_parse_auto_config(struct hda_codec *codec,
3665 const hda_nid_t *ignore_nids,
3666 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003667{
3668 struct alc_spec *spec = codec->spec;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003669 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003670 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003671
Takashi Iwai23c09b02011-08-19 09:05:35 +02003672 err = snd_hda_parse_pin_def_config(codec, cfg, ignore_nids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003673 if (err < 0)
3674 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003675 if (!cfg->line_outs) {
3676 if (cfg->dig_outs || cfg->dig_in_pin) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003677 spec->multiout.max_channels = 2;
3678 spec->no_analog = 1;
3679 goto dig_only;
3680 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003681 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003682 }
Takashi Iwai23c09b02011-08-19 09:05:35 +02003683
3684 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3685 /* use HP as primary out */
3686 cfg->speaker_outs = cfg->line_outs;
3687 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3688 sizeof(cfg->speaker_pins));
3689 cfg->line_outs = cfg->hp_outs;
3690 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3691 cfg->hp_outs = 0;
3692 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3693 cfg->line_out_type = AUTO_PIN_HP_OUT;
3694 }
3695
Takashi Iwai1d045db2011-07-07 18:23:21 +02003696 err = alc_auto_fill_dac_nids(codec);
3697 if (err < 0)
3698 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003699 err = alc_auto_add_multi_channel_mode(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003700 if (err < 0)
3701 return err;
Takashi Iwai23c09b02011-08-19 09:05:35 +02003702 err = alc_auto_fill_extra_dacs(codec);
3703 if (err < 0)
3704 return err;
3705 err = alc_auto_create_multi_out_ctls(codec, cfg);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003706 if (err < 0)
3707 return err;
3708 err = alc_auto_create_hp_out(codec);
3709 if (err < 0)
3710 return err;
3711 err = alc_auto_create_speaker_out(codec);
3712 if (err < 0)
3713 return err;
3714 err = alc_auto_create_input_ctls(codec);
3715 if (err < 0)
3716 return err;
3717
3718 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3719
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003720 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02003721 alc_auto_parse_digital(codec);
3722
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003723 if (!spec->no_analog)
3724 alc_remove_invalid_adc_nids(codec);
3725
3726 if (ssid_nids)
3727 alc_ssid_check(codec, ssid_nids);
3728
3729 if (!spec->no_analog) {
3730 alc_auto_check_switches(codec);
3731 err = alc_auto_add_mic_boost(codec);
3732 if (err < 0)
3733 return err;
3734 }
3735
Takashi Iwai1d045db2011-07-07 18:23:21 +02003736 if (spec->kctls.list)
3737 add_mixer(spec, spec->kctls.list);
3738
Takashi Iwai1d045db2011-07-07 18:23:21 +02003739 return 1;
3740}
3741
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003742static int alc880_parse_auto_config(struct hda_codec *codec)
3743{
3744 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3745 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3746 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
3747}
3748
Takashi Iwai1d045db2011-07-07 18:23:21 +02003749#ifdef CONFIG_SND_HDA_POWER_SAVE
3750static const struct hda_amp_list alc880_loopbacks[] = {
3751 { 0x0b, HDA_INPUT, 0 },
3752 { 0x0b, HDA_INPUT, 1 },
3753 { 0x0b, HDA_INPUT, 2 },
3754 { 0x0b, HDA_INPUT, 3 },
3755 { 0x0b, HDA_INPUT, 4 },
3756 { } /* end */
3757};
3758#endif
3759
3760/*
3761 * board setups
3762 */
3763#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3764#define alc_board_config \
3765 snd_hda_check_board_config
3766#define alc_board_codec_sid_config \
3767 snd_hda_check_board_codec_sid_config
3768#include "alc_quirks.c"
3769#else
3770#define alc_board_config(codec, nums, models, tbl) -1
3771#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3772#define setup_preset(codec, x) /* NOP */
3773#endif
3774
3775/*
3776 * OK, here we have finally the patch for ALC880
3777 */
3778#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3779#include "alc880_quirks.c"
3780#endif
3781
3782static int patch_alc880(struct hda_codec *codec)
3783{
3784 struct alc_spec *spec;
3785 int board_config;
3786 int err;
3787
3788 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3789 if (spec == NULL)
3790 return -ENOMEM;
3791
3792 codec->spec = spec;
3793
3794 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003795 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003796
3797 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3798 alc880_models, alc880_cfg_tbl);
3799 if (board_config < 0) {
3800 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3801 codec->chip_name);
3802 board_config = ALC_MODEL_AUTO;
3803 }
3804
3805 if (board_config == ALC_MODEL_AUTO) {
3806 /* automatic parse from the BIOS config */
3807 err = alc880_parse_auto_config(codec);
3808 if (err < 0) {
3809 alc_free(codec);
3810 return err;
3811 }
3812#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3813 else if (!err) {
3814 printk(KERN_INFO
3815 "hda_codec: Cannot set up configuration "
3816 "from BIOS. Using 3-stack mode...\n");
3817 board_config = ALC880_3ST;
3818 }
3819#endif
3820 }
3821
Takashi Iwai1d045db2011-07-07 18:23:21 +02003822 if (board_config != ALC_MODEL_AUTO)
3823 setup_preset(codec, &alc880_presets[board_config]);
3824
Takashi Iwai60a6a842011-07-27 14:01:24 +02003825 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003826 alc_auto_fill_adc_caps(codec);
3827 alc_rebuild_imux_for_auto_mic(codec);
3828 alc_remove_invalid_adc_nids(codec);
3829 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003830
3831 if (!spec->no_analog && !spec->cap_mixer)
3832 set_capture_mixer(codec);
3833
3834 if (!spec->no_analog) {
3835 err = snd_hda_attach_beep_device(codec, 0x1);
3836 if (err < 0) {
3837 alc_free(codec);
3838 return err;
3839 }
3840 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3841 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003842
3843 spec->vmaster_nid = 0x0c;
3844
3845 codec->patch_ops = alc_patch_ops;
3846 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003847 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003848#ifdef CONFIG_SND_HDA_POWER_SAVE
3849 if (!spec->loopback.amplist)
3850 spec->loopback.amplist = alc880_loopbacks;
3851#endif
3852
3853 return 0;
3854}
3855
3856
3857/*
3858 * ALC260 support
3859 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003860static int alc260_parse_auto_config(struct hda_codec *codec)
3861{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003862 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003863 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
3864 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003865}
3866
Takashi Iwai1d045db2011-07-07 18:23:21 +02003867#ifdef CONFIG_SND_HDA_POWER_SAVE
3868static const struct hda_amp_list alc260_loopbacks[] = {
3869 { 0x07, HDA_INPUT, 0 },
3870 { 0x07, HDA_INPUT, 1 },
3871 { 0x07, HDA_INPUT, 2 },
3872 { 0x07, HDA_INPUT, 3 },
3873 { 0x07, HDA_INPUT, 4 },
3874 { } /* end */
3875};
3876#endif
3877
3878/*
3879 * Pin config fixes
3880 */
3881enum {
3882 PINFIX_HP_DC5750,
3883};
3884
3885static const struct alc_fixup alc260_fixups[] = {
3886 [PINFIX_HP_DC5750] = {
3887 .type = ALC_FIXUP_PINS,
3888 .v.pins = (const struct alc_pincfg[]) {
3889 { 0x11, 0x90130110 }, /* speaker */
3890 { }
3891 }
3892 },
3893};
3894
3895static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3896 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3897 {}
3898};
3899
3900/*
3901 */
3902#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3903#include "alc260_quirks.c"
3904#endif
3905
3906static int patch_alc260(struct hda_codec *codec)
3907{
3908 struct alc_spec *spec;
3909 int err, board_config;
3910
3911 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3912 if (spec == NULL)
3913 return -ENOMEM;
3914
3915 codec->spec = spec;
3916
3917 spec->mixer_nid = 0x07;
3918
3919 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3920 alc260_models, alc260_cfg_tbl);
3921 if (board_config < 0) {
3922 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3923 codec->chip_name);
3924 board_config = ALC_MODEL_AUTO;
3925 }
3926
3927 if (board_config == ALC_MODEL_AUTO) {
3928 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3929 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3930 }
3931
3932 if (board_config == ALC_MODEL_AUTO) {
3933 /* automatic parse from the BIOS config */
3934 err = alc260_parse_auto_config(codec);
3935 if (err < 0) {
3936 alc_free(codec);
3937 return err;
3938 }
3939#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3940 else if (!err) {
3941 printk(KERN_INFO
3942 "hda_codec: Cannot set up configuration "
3943 "from BIOS. Using base mode...\n");
3944 board_config = ALC260_BASIC;
3945 }
3946#endif
3947 }
3948
Takashi Iwai1d045db2011-07-07 18:23:21 +02003949 if (board_config != ALC_MODEL_AUTO)
3950 setup_preset(codec, &alc260_presets[board_config]);
3951
Takashi Iwai60a6a842011-07-27 14:01:24 +02003952 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003953 alc_auto_fill_adc_caps(codec);
3954 alc_rebuild_imux_for_auto_mic(codec);
3955 alc_remove_invalid_adc_nids(codec);
3956 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003957
3958 if (!spec->no_analog && !spec->cap_mixer)
3959 set_capture_mixer(codec);
3960
3961 if (!spec->no_analog) {
3962 err = snd_hda_attach_beep_device(codec, 0x1);
3963 if (err < 0) {
3964 alc_free(codec);
3965 return err;
3966 }
3967 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3968 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003969
3970 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3971
3972 spec->vmaster_nid = 0x08;
3973
3974 codec->patch_ops = alc_patch_ops;
3975 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02003976 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003977 spec->shutup = alc_eapd_shutup;
3978#ifdef CONFIG_SND_HDA_POWER_SAVE
3979 if (!spec->loopback.amplist)
3980 spec->loopback.amplist = alc260_loopbacks;
3981#endif
3982
3983 return 0;
3984}
3985
3986
3987/*
3988 * ALC882/883/885/888/889 support
3989 *
3990 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3991 * configuration. Each pin widget can choose any input DACs and a mixer.
3992 * Each ADC is connected from a mixer of all inputs. This makes possible
3993 * 6-channel independent captures.
3994 *
3995 * In addition, an independent DAC for the multi-playback (not used in this
3996 * driver yet).
3997 */
3998#ifdef CONFIG_SND_HDA_POWER_SAVE
3999#define alc882_loopbacks alc880_loopbacks
4000#endif
4001
4002/*
4003 * Pin config fixes
4004 */
4005enum {
4006 PINFIX_ABIT_AW9D_MAX,
4007 PINFIX_LENOVO_Y530,
4008 PINFIX_PB_M5210,
4009 PINFIX_ACER_ASPIRE_7736,
4010};
4011
4012static const struct alc_fixup alc882_fixups[] = {
4013 [PINFIX_ABIT_AW9D_MAX] = {
4014 .type = ALC_FIXUP_PINS,
4015 .v.pins = (const struct alc_pincfg[]) {
4016 { 0x15, 0x01080104 }, /* side */
4017 { 0x16, 0x01011012 }, /* rear */
4018 { 0x17, 0x01016011 }, /* clfe */
4019 { }
4020 }
4021 },
4022 [PINFIX_LENOVO_Y530] = {
4023 .type = ALC_FIXUP_PINS,
4024 .v.pins = (const struct alc_pincfg[]) {
4025 { 0x15, 0x99130112 }, /* rear int speakers */
4026 { 0x16, 0x99130111 }, /* subwoofer */
4027 { }
4028 }
4029 },
4030 [PINFIX_PB_M5210] = {
4031 .type = ALC_FIXUP_VERBS,
4032 .v.verbs = (const struct hda_verb[]) {
4033 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
4034 {}
4035 }
4036 },
4037 [PINFIX_ACER_ASPIRE_7736] = {
4038 .type = ALC_FIXUP_SKU,
4039 .v.sku = ALC_FIXUP_SKU_IGNORE,
4040 },
4041};
4042
4043static const struct snd_pci_quirk alc882_fixup_tbl[] = {
4044 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
4045 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
4046 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
4047 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
4048 {}
4049};
4050
4051/*
4052 * BIOS auto configuration
4053 */
4054/* almost identical with ALC880 parser... */
4055static int alc882_parse_auto_config(struct hda_codec *codec)
4056{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004057 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004058 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4059 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004060}
4061
Takashi Iwai1d045db2011-07-07 18:23:21 +02004062/*
4063 */
4064#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4065#include "alc882_quirks.c"
4066#endif
4067
4068static int patch_alc882(struct hda_codec *codec)
4069{
4070 struct alc_spec *spec;
4071 int err, board_config;
4072
4073 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4074 if (spec == NULL)
4075 return -ENOMEM;
4076
4077 codec->spec = spec;
4078
4079 spec->mixer_nid = 0x0b;
4080
4081 switch (codec->vendor_id) {
4082 case 0x10ec0882:
4083 case 0x10ec0885:
4084 break;
4085 default:
4086 /* ALC883 and variants */
4087 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4088 break;
4089 }
4090
4091 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
4092 alc882_models, alc882_cfg_tbl);
4093
4094 if (board_config < 0)
4095 board_config = alc_board_codec_sid_config(codec,
4096 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
4097
4098 if (board_config < 0) {
4099 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4100 codec->chip_name);
4101 board_config = ALC_MODEL_AUTO;
4102 }
4103
4104 if (board_config == ALC_MODEL_AUTO) {
4105 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
4106 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4107 }
4108
4109 alc_auto_parse_customize_define(codec);
4110
4111 if (board_config == ALC_MODEL_AUTO) {
4112 /* automatic parse from the BIOS config */
4113 err = alc882_parse_auto_config(codec);
4114 if (err < 0) {
4115 alc_free(codec);
4116 return err;
4117 }
4118#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4119 else if (!err) {
4120 printk(KERN_INFO
4121 "hda_codec: Cannot set up configuration "
4122 "from BIOS. Using base mode...\n");
4123 board_config = ALC882_3ST_DIG;
4124 }
4125#endif
4126 }
4127
Takashi Iwai1d045db2011-07-07 18:23:21 +02004128 if (board_config != ALC_MODEL_AUTO)
4129 setup_preset(codec, &alc882_presets[board_config]);
4130
Takashi Iwai60a6a842011-07-27 14:01:24 +02004131 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004132 alc_auto_fill_adc_caps(codec);
4133 alc_rebuild_imux_for_auto_mic(codec);
4134 alc_remove_invalid_adc_nids(codec);
4135 }
4136
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004137 if (!spec->no_analog && !spec->cap_mixer)
4138 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004139
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004140 if (!spec->no_analog && has_cdefine_beep(codec)) {
4141 err = snd_hda_attach_beep_device(codec, 0x1);
4142 if (err < 0) {
4143 alc_free(codec);
4144 return err;
4145 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004146 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004147 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004148
4149 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4150
4151 spec->vmaster_nid = 0x0c;
4152
4153 codec->patch_ops = alc_patch_ops;
4154 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004155 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004156
4157 alc_init_jacks(codec);
4158#ifdef CONFIG_SND_HDA_POWER_SAVE
4159 if (!spec->loopback.amplist)
4160 spec->loopback.amplist = alc882_loopbacks;
4161#endif
4162
4163 return 0;
4164}
4165
4166
4167/*
4168 * ALC262 support
4169 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004170static int alc262_parse_auto_config(struct hda_codec *codec)
4171{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004172 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004173 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4174 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004175}
4176
4177/*
4178 * Pin config fixes
4179 */
4180enum {
4181 PINFIX_FSC_H270,
4182 PINFIX_HP_Z200,
4183};
4184
4185static const struct alc_fixup alc262_fixups[] = {
4186 [PINFIX_FSC_H270] = {
4187 .type = ALC_FIXUP_PINS,
4188 .v.pins = (const struct alc_pincfg[]) {
4189 { 0x14, 0x99130110 }, /* speaker */
4190 { 0x15, 0x0221142f }, /* front HP */
4191 { 0x1b, 0x0121141f }, /* rear HP */
4192 { }
4193 }
4194 },
4195 [PINFIX_HP_Z200] = {
4196 .type = ALC_FIXUP_PINS,
4197 .v.pins = (const struct alc_pincfg[]) {
4198 { 0x16, 0x99130120 }, /* internal speaker */
4199 { }
4200 }
4201 },
4202};
4203
4204static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4205 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4206 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4207 {}
4208};
4209
4210
4211#ifdef CONFIG_SND_HDA_POWER_SAVE
4212#define alc262_loopbacks alc880_loopbacks
4213#endif
4214
Takashi Iwai1d045db2011-07-07 18:23:21 +02004215/*
4216 */
4217#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4218#include "alc262_quirks.c"
4219#endif
4220
4221static int patch_alc262(struct hda_codec *codec)
4222{
4223 struct alc_spec *spec;
4224 int board_config;
4225 int err;
4226
4227 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4228 if (spec == NULL)
4229 return -ENOMEM;
4230
4231 codec->spec = spec;
4232
4233 spec->mixer_nid = 0x0b;
4234
4235#if 0
4236 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4237 * under-run
4238 */
4239 {
4240 int tmp;
4241 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4242 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4243 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4244 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4245 }
4246#endif
4247 alc_auto_parse_customize_define(codec);
4248
4249 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4250
4251 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4252 alc262_models, alc262_cfg_tbl);
4253
4254 if (board_config < 0) {
4255 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4256 codec->chip_name);
4257 board_config = ALC_MODEL_AUTO;
4258 }
4259
4260 if (board_config == ALC_MODEL_AUTO) {
4261 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4262 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4263 }
4264
4265 if (board_config == ALC_MODEL_AUTO) {
4266 /* automatic parse from the BIOS config */
4267 err = alc262_parse_auto_config(codec);
4268 if (err < 0) {
4269 alc_free(codec);
4270 return err;
4271 }
4272#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4273 else if (!err) {
4274 printk(KERN_INFO
4275 "hda_codec: Cannot set up configuration "
4276 "from BIOS. Using base mode...\n");
4277 board_config = ALC262_BASIC;
4278 }
4279#endif
4280 }
4281
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004282 if (board_config != ALC_MODEL_AUTO)
4283 setup_preset(codec, &alc262_presets[board_config]);
4284
Takashi Iwai60a6a842011-07-27 14:01:24 +02004285 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004286 alc_auto_fill_adc_caps(codec);
4287 alc_rebuild_imux_for_auto_mic(codec);
4288 alc_remove_invalid_adc_nids(codec);
4289 }
4290
4291 if (!spec->no_analog && !spec->cap_mixer)
4292 set_capture_mixer(codec);
4293
Takashi Iwai1d045db2011-07-07 18:23:21 +02004294 if (!spec->no_analog && has_cdefine_beep(codec)) {
4295 err = snd_hda_attach_beep_device(codec, 0x1);
4296 if (err < 0) {
4297 alc_free(codec);
4298 return err;
4299 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004300 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004301 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004302
4303 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4304
4305 spec->vmaster_nid = 0x0c;
4306
4307 codec->patch_ops = alc_patch_ops;
4308 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004309 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004310 spec->shutup = alc_eapd_shutup;
4311
4312 alc_init_jacks(codec);
4313#ifdef CONFIG_SND_HDA_POWER_SAVE
4314 if (!spec->loopback.amplist)
4315 spec->loopback.amplist = alc262_loopbacks;
4316#endif
4317
4318 return 0;
4319}
4320
4321/*
4322 * ALC268
4323 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004324/* bind Beep switches of both NID 0x0f and 0x10 */
4325static const struct hda_bind_ctls alc268_bind_beep_sw = {
4326 .ops = &snd_hda_bind_sw,
4327 .values = {
4328 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4329 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4330 0
4331 },
4332};
4333
4334static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4335 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4336 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4337 { }
4338};
4339
4340/* set PCBEEP vol = 0, mute connections */
4341static const struct hda_verb alc268_beep_init_verbs[] = {
4342 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4343 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4344 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4345 { }
4346};
4347
4348/*
4349 * BIOS auto configuration
4350 */
4351static int alc268_parse_auto_config(struct hda_codec *codec)
4352{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004353 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004354 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004355 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4356 if (err > 0) {
4357 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4358 add_mixer(spec, alc268_beep_mixer);
4359 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004360 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004361 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004362 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004363}
4364
Takashi Iwai1d045db2011-07-07 18:23:21 +02004365/*
4366 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004367static int patch_alc268(struct hda_codec *codec)
4368{
4369 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004370 int i, has_beep, err;
4371
4372 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4373 if (spec == NULL)
4374 return -ENOMEM;
4375
4376 codec->spec = spec;
4377
4378 /* ALC268 has no aa-loopback mixer */
4379
Takashi Iwai6ebb8052011-08-16 15:15:40 +02004380 /* automatic parse from the BIOS config */
4381 err = alc268_parse_auto_config(codec);
4382 if (err < 0) {
4383 alc_free(codec);
4384 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004385 }
4386
Takashi Iwai1d045db2011-07-07 18:23:21 +02004387 has_beep = 0;
4388 for (i = 0; i < spec->num_mixers; i++) {
4389 if (spec->mixers[i] == alc268_beep_mixer) {
4390 has_beep = 1;
4391 break;
4392 }
4393 }
4394
4395 if (has_beep) {
4396 err = snd_hda_attach_beep_device(codec, 0x1);
4397 if (err < 0) {
4398 alc_free(codec);
4399 return err;
4400 }
4401 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4402 /* override the amp caps for beep generator */
4403 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4404 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4405 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4406 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4407 (0 << AC_AMPCAP_MUTE_SHIFT));
4408 }
4409
Takashi Iwai60a6a842011-07-27 14:01:24 +02004410 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004411 alc_auto_fill_adc_caps(codec);
4412 alc_rebuild_imux_for_auto_mic(codec);
4413 alc_remove_invalid_adc_nids(codec);
4414 }
4415
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004416 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004417 set_capture_mixer(codec);
4418
4419 spec->vmaster_nid = 0x02;
4420
4421 codec->patch_ops = alc_patch_ops;
Takashi Iwai6ebb8052011-08-16 15:15:40 +02004422 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004423 spec->shutup = alc_eapd_shutup;
4424
4425 alc_init_jacks(codec);
4426
4427 return 0;
4428}
4429
4430/*
4431 * ALC269
4432 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004433#ifdef CONFIG_SND_HDA_POWER_SAVE
4434#define alc269_loopbacks alc880_loopbacks
4435#endif
4436
4437static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4438 .substreams = 1,
4439 .channels_min = 2,
4440 .channels_max = 8,
4441 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4442 /* NID is set in alc_build_pcms */
4443 .ops = {
4444 .open = alc_playback_pcm_open,
4445 .prepare = alc_playback_pcm_prepare,
4446 .cleanup = alc_playback_pcm_cleanup
4447 },
4448};
4449
4450static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4451 .substreams = 1,
4452 .channels_min = 2,
4453 .channels_max = 2,
4454 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4455 /* NID is set in alc_build_pcms */
4456};
4457
4458#ifdef CONFIG_SND_HDA_POWER_SAVE
4459static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4460{
4461 switch (codec->subsystem_id) {
4462 case 0x103c1586:
4463 return 1;
4464 }
4465 return 0;
4466}
4467
4468static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4469{
4470 /* update mute-LED according to the speaker mute state */
4471 if (nid == 0x01 || nid == 0x14) {
4472 int pinval;
4473 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4474 HDA_AMP_MUTE)
4475 pinval = 0x24;
4476 else
4477 pinval = 0x20;
4478 /* mic2 vref pin is used for mute LED control */
4479 snd_hda_codec_update_cache(codec, 0x19, 0,
4480 AC_VERB_SET_PIN_WIDGET_CONTROL,
4481 pinval);
4482 }
4483 return alc_check_power_status(codec, nid);
4484}
4485#endif /* CONFIG_SND_HDA_POWER_SAVE */
4486
4487/* different alc269-variants */
4488enum {
4489 ALC269_TYPE_ALC269VA,
4490 ALC269_TYPE_ALC269VB,
4491 ALC269_TYPE_ALC269VC,
4492};
4493
4494/*
4495 * BIOS auto configuration
4496 */
4497static int alc269_parse_auto_config(struct hda_codec *codec)
4498{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004499 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004500 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
4501 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4502 struct alc_spec *spec = codec->spec;
4503 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
4504 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004505
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004506 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004507}
4508
Takashi Iwai1d045db2011-07-07 18:23:21 +02004509static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4510{
4511 int val = alc_read_coef_idx(codec, 0x04);
4512 if (power_up)
4513 val |= 1 << 11;
4514 else
4515 val &= ~(1 << 11);
4516 alc_write_coef_idx(codec, 0x04, val);
4517}
4518
4519static void alc269_shutup(struct hda_codec *codec)
4520{
4521 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4522 alc269_toggle_power_output(codec, 0);
4523 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4524 alc269_toggle_power_output(codec, 0);
4525 msleep(150);
4526 }
4527}
4528
Takashi Iwai2a439522011-07-26 09:52:50 +02004529#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004530static int alc269_resume(struct hda_codec *codec)
4531{
4532 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4533 alc269_toggle_power_output(codec, 0);
4534 msleep(150);
4535 }
4536
4537 codec->patch_ops.init(codec);
4538
4539 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4540 alc269_toggle_power_output(codec, 1);
4541 msleep(200);
4542 }
4543
4544 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4545 alc269_toggle_power_output(codec, 1);
4546
4547 snd_hda_codec_resume_amp(codec);
4548 snd_hda_codec_resume_cache(codec);
4549 hda_call_check_power_status(codec, 0x01);
4550 return 0;
4551}
Takashi Iwai2a439522011-07-26 09:52:50 +02004552#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004553
4554static void alc269_fixup_hweq(struct hda_codec *codec,
4555 const struct alc_fixup *fix, int action)
4556{
4557 int coef;
4558
4559 if (action != ALC_FIXUP_ACT_INIT)
4560 return;
4561 coef = alc_read_coef_idx(codec, 0x1e);
4562 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4563}
4564
4565static void alc271_fixup_dmic(struct hda_codec *codec,
4566 const struct alc_fixup *fix, int action)
4567{
4568 static const struct hda_verb verbs[] = {
4569 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4570 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4571 {}
4572 };
4573 unsigned int cfg;
4574
4575 if (strcmp(codec->chip_name, "ALC271X"))
4576 return;
4577 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4578 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4579 snd_hda_sequence_write(codec, verbs);
4580}
4581
Takashi Iwai017f2a12011-07-09 14:42:25 +02004582static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4583 const struct alc_fixup *fix, int action)
4584{
4585 struct alc_spec *spec = codec->spec;
4586
4587 if (action != ALC_FIXUP_ACT_PROBE)
4588 return;
4589
4590 /* Due to a hardware problem on Lenovo Ideadpad, we need to
4591 * fix the sample rate of analog I/O to 44.1kHz
4592 */
4593 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
4594 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4595}
4596
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004597static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4598 const struct alc_fixup *fix, int action)
4599{
4600 int coef;
4601
4602 if (action != ALC_FIXUP_ACT_INIT)
4603 return;
4604 /* The digital-mic unit sends PDM (differential signal) instead of
4605 * the standard PCM, thus you can't record a valid mono stream as is.
4606 * Below is a workaround specific to ALC269 to control the dmic
4607 * signal source as mono.
4608 */
4609 coef = alc_read_coef_idx(codec, 0x07);
4610 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4611}
4612
Takashi Iwai24519912011-08-16 15:08:49 +02004613static void alc269_quanta_automute(struct hda_codec *codec)
4614{
4615 update_speakers(codec);
4616
4617 snd_hda_codec_write(codec, 0x20, 0,
4618 AC_VERB_SET_COEF_INDEX, 0x0c);
4619 snd_hda_codec_write(codec, 0x20, 0,
4620 AC_VERB_SET_PROC_COEF, 0x680);
4621
4622 snd_hda_codec_write(codec, 0x20, 0,
4623 AC_VERB_SET_COEF_INDEX, 0x0c);
4624 snd_hda_codec_write(codec, 0x20, 0,
4625 AC_VERB_SET_PROC_COEF, 0x480);
4626}
4627
4628static void alc269_fixup_quanta_mute(struct hda_codec *codec,
4629 const struct alc_fixup *fix, int action)
4630{
4631 struct alc_spec *spec = codec->spec;
4632 if (action != ALC_FIXUP_ACT_PROBE)
4633 return;
4634 spec->automute_hook = alc269_quanta_automute;
4635}
4636
Takashi Iwai1d045db2011-07-07 18:23:21 +02004637enum {
4638 ALC269_FIXUP_SONY_VAIO,
4639 ALC275_FIXUP_SONY_VAIO_GPIO2,
4640 ALC269_FIXUP_DELL_M101Z,
4641 ALC269_FIXUP_SKU_IGNORE,
4642 ALC269_FIXUP_ASUS_G73JW,
4643 ALC269_FIXUP_LENOVO_EAPD,
4644 ALC275_FIXUP_SONY_HWEQ,
4645 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004646 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004647 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai24519912011-08-16 15:08:49 +02004648 ALC269_FIXUP_QUANTA_MUTE,
4649 ALC269_FIXUP_LIFEBOOK,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004650};
4651
4652static const struct alc_fixup alc269_fixups[] = {
4653 [ALC269_FIXUP_SONY_VAIO] = {
4654 .type = ALC_FIXUP_VERBS,
4655 .v.verbs = (const struct hda_verb[]) {
4656 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4657 {}
4658 }
4659 },
4660 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4661 .type = ALC_FIXUP_VERBS,
4662 .v.verbs = (const struct hda_verb[]) {
4663 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4664 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4665 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4666 { }
4667 },
4668 .chained = true,
4669 .chain_id = ALC269_FIXUP_SONY_VAIO
4670 },
4671 [ALC269_FIXUP_DELL_M101Z] = {
4672 .type = ALC_FIXUP_VERBS,
4673 .v.verbs = (const struct hda_verb[]) {
4674 /* Enables internal speaker */
4675 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4676 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4677 {}
4678 }
4679 },
4680 [ALC269_FIXUP_SKU_IGNORE] = {
4681 .type = ALC_FIXUP_SKU,
4682 .v.sku = ALC_FIXUP_SKU_IGNORE,
4683 },
4684 [ALC269_FIXUP_ASUS_G73JW] = {
4685 .type = ALC_FIXUP_PINS,
4686 .v.pins = (const struct alc_pincfg[]) {
4687 { 0x17, 0x99130111 }, /* subwoofer */
4688 { }
4689 }
4690 },
4691 [ALC269_FIXUP_LENOVO_EAPD] = {
4692 .type = ALC_FIXUP_VERBS,
4693 .v.verbs = (const struct hda_verb[]) {
4694 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4695 {}
4696 }
4697 },
4698 [ALC275_FIXUP_SONY_HWEQ] = {
4699 .type = ALC_FIXUP_FUNC,
4700 .v.func = alc269_fixup_hweq,
4701 .chained = true,
4702 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4703 },
4704 [ALC271_FIXUP_DMIC] = {
4705 .type = ALC_FIXUP_FUNC,
4706 .v.func = alc271_fixup_dmic,
4707 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004708 [ALC269_FIXUP_PCM_44K] = {
4709 .type = ALC_FIXUP_FUNC,
4710 .v.func = alc269_fixup_pcm_44k,
4711 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004712 [ALC269_FIXUP_STEREO_DMIC] = {
4713 .type = ALC_FIXUP_FUNC,
4714 .v.func = alc269_fixup_stereo_dmic,
4715 },
Takashi Iwai24519912011-08-16 15:08:49 +02004716 [ALC269_FIXUP_QUANTA_MUTE] = {
4717 .type = ALC_FIXUP_FUNC,
4718 .v.func = alc269_fixup_quanta_mute,
4719 },
4720 [ALC269_FIXUP_LIFEBOOK] = {
4721 .type = ALC_FIXUP_PINS,
4722 .v.pins = (const struct alc_pincfg[]) {
4723 { 0x1a, 0x2101103f }, /* dock line-out */
4724 { 0x1b, 0x23a11040 }, /* dock mic-in */
4725 { }
4726 },
4727 .chained = true,
4728 .chain_id = ALC269_FIXUP_QUANTA_MUTE
4729 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004730};
4731
4732static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02004733 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004734 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4735 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4736 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4737 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4738 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004739 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4740 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4741 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4742 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4743 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4744 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
Takashi Iwai24519912011-08-16 15:08:49 +02004745 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004746 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4747 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4748 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4749 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4750 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai24519912011-08-16 15:08:49 +02004751 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02004752 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004753 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
4754 {}
4755};
4756
4757
4758static int alc269_fill_coef(struct hda_codec *codec)
4759{
4760 int val;
4761
4762 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4763 alc_write_coef_idx(codec, 0xf, 0x960b);
4764 alc_write_coef_idx(codec, 0xe, 0x8817);
4765 }
4766
4767 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4768 alc_write_coef_idx(codec, 0xf, 0x960b);
4769 alc_write_coef_idx(codec, 0xe, 0x8814);
4770 }
4771
4772 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4773 val = alc_read_coef_idx(codec, 0x04);
4774 /* Power up output pin */
4775 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4776 }
4777
4778 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4779 val = alc_read_coef_idx(codec, 0xd);
4780 if ((val & 0x0c00) >> 10 != 0x1) {
4781 /* Capless ramp up clock control */
4782 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4783 }
4784 val = alc_read_coef_idx(codec, 0x17);
4785 if ((val & 0x01c0) >> 6 != 0x4) {
4786 /* Class D power on reset */
4787 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4788 }
4789 }
4790
4791 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4792 alc_write_coef_idx(codec, 0xd, val | (1<<14));
4793
4794 val = alc_read_coef_idx(codec, 0x4); /* HP */
4795 alc_write_coef_idx(codec, 0x4, val | (1<<11));
4796
4797 return 0;
4798}
4799
4800/*
4801 */
4802#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4803#include "alc269_quirks.c"
4804#endif
4805
4806static int patch_alc269(struct hda_codec *codec)
4807{
4808 struct alc_spec *spec;
4809 int board_config, coef;
4810 int err;
4811
4812 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4813 if (spec == NULL)
4814 return -ENOMEM;
4815
4816 codec->spec = spec;
4817
4818 spec->mixer_nid = 0x0b;
4819
4820 alc_auto_parse_customize_define(codec);
4821
4822 if (codec->vendor_id == 0x10ec0269) {
4823 spec->codec_variant = ALC269_TYPE_ALC269VA;
4824 coef = alc_read_coef_idx(codec, 0);
4825 if ((coef & 0x00f0) == 0x0010) {
4826 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
4827 spec->cdefine.platform_type == 1) {
4828 alc_codec_rename(codec, "ALC271X");
4829 } else if ((coef & 0xf000) == 0x2000) {
4830 alc_codec_rename(codec, "ALC259");
4831 } else if ((coef & 0xf000) == 0x3000) {
4832 alc_codec_rename(codec, "ALC258");
4833 } else if ((coef & 0xfff0) == 0x3010) {
4834 alc_codec_rename(codec, "ALC277");
4835 } else {
4836 alc_codec_rename(codec, "ALC269VB");
4837 }
4838 spec->codec_variant = ALC269_TYPE_ALC269VB;
4839 } else if ((coef & 0x00f0) == 0x0020) {
4840 if (coef == 0xa023)
4841 alc_codec_rename(codec, "ALC259");
4842 else if (coef == 0x6023)
4843 alc_codec_rename(codec, "ALC281X");
4844 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4845 codec->bus->pci->subsystem_device == 0x21f3)
4846 alc_codec_rename(codec, "ALC3202");
4847 else
4848 alc_codec_rename(codec, "ALC269VC");
4849 spec->codec_variant = ALC269_TYPE_ALC269VC;
4850 } else
4851 alc_fix_pll_init(codec, 0x20, 0x04, 15);
4852 alc269_fill_coef(codec);
4853 }
4854
4855 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
4856 alc269_models, alc269_cfg_tbl);
4857
4858 if (board_config < 0) {
4859 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4860 codec->chip_name);
4861 board_config = ALC_MODEL_AUTO;
4862 }
4863
4864 if (board_config == ALC_MODEL_AUTO) {
4865 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
4866 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4867 }
4868
4869 if (board_config == ALC_MODEL_AUTO) {
4870 /* automatic parse from the BIOS config */
4871 err = alc269_parse_auto_config(codec);
4872 if (err < 0) {
4873 alc_free(codec);
4874 return err;
4875 }
4876#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4877 else if (!err) {
4878 printk(KERN_INFO
4879 "hda_codec: Cannot set up configuration "
4880 "from BIOS. Using base mode...\n");
4881 board_config = ALC269_BASIC;
4882 }
4883#endif
4884 }
4885
Takashi Iwai1d045db2011-07-07 18:23:21 +02004886 if (board_config != ALC_MODEL_AUTO)
4887 setup_preset(codec, &alc269_presets[board_config]);
4888
Takashi Iwai60a6a842011-07-27 14:01:24 +02004889 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004890 alc_auto_fill_adc_caps(codec);
4891 alc_rebuild_imux_for_auto_mic(codec);
4892 alc_remove_invalid_adc_nids(codec);
4893 }
4894
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004895 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004896 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004897
4898 if (!spec->no_analog && has_cdefine_beep(codec)) {
4899 err = snd_hda_attach_beep_device(codec, 0x1);
4900 if (err < 0) {
4901 alc_free(codec);
4902 return err;
4903 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004904 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004905 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004906
4907 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4908
4909 spec->vmaster_nid = 0x02;
4910
4911 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02004912#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004913 codec->patch_ops.resume = alc269_resume;
4914#endif
4915 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004916 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004917 spec->shutup = alc269_shutup;
4918
4919 alc_init_jacks(codec);
4920#ifdef CONFIG_SND_HDA_POWER_SAVE
4921 if (!spec->loopback.amplist)
4922 spec->loopback.amplist = alc269_loopbacks;
4923 if (alc269_mic2_for_mute_led(codec))
4924 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
4925#endif
4926
4927 return 0;
4928}
4929
4930/*
4931 * ALC861
4932 */
4933
Takashi Iwai1d045db2011-07-07 18:23:21 +02004934static int alc861_parse_auto_config(struct hda_codec *codec)
4935{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004936 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004937 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4938 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004939}
4940
Takashi Iwai1d045db2011-07-07 18:23:21 +02004941#ifdef CONFIG_SND_HDA_POWER_SAVE
4942static const struct hda_amp_list alc861_loopbacks[] = {
4943 { 0x15, HDA_INPUT, 0 },
4944 { 0x15, HDA_INPUT, 1 },
4945 { 0x15, HDA_INPUT, 2 },
4946 { 0x15, HDA_INPUT, 3 },
4947 { } /* end */
4948};
4949#endif
4950
4951
4952/* Pin config fixes */
4953enum {
4954 PINFIX_FSC_AMILO_PI1505,
4955};
4956
4957static const struct alc_fixup alc861_fixups[] = {
4958 [PINFIX_FSC_AMILO_PI1505] = {
4959 .type = ALC_FIXUP_PINS,
4960 .v.pins = (const struct alc_pincfg[]) {
4961 { 0x0b, 0x0221101f }, /* HP */
4962 { 0x0f, 0x90170310 }, /* speaker */
4963 { }
4964 }
4965 },
4966};
4967
4968static const struct snd_pci_quirk alc861_fixup_tbl[] = {
4969 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
4970 {}
4971};
4972
4973/*
4974 */
4975#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4976#include "alc861_quirks.c"
4977#endif
4978
4979static int patch_alc861(struct hda_codec *codec)
4980{
4981 struct alc_spec *spec;
4982 int board_config;
4983 int err;
4984
4985 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4986 if (spec == NULL)
4987 return -ENOMEM;
4988
4989 codec->spec = spec;
4990
4991 spec->mixer_nid = 0x15;
4992
4993 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
4994 alc861_models, alc861_cfg_tbl);
4995
4996 if (board_config < 0) {
4997 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4998 codec->chip_name);
4999 board_config = ALC_MODEL_AUTO;
5000 }
5001
5002 if (board_config == ALC_MODEL_AUTO) {
5003 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
5004 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5005 }
5006
5007 if (board_config == ALC_MODEL_AUTO) {
5008 /* automatic parse from the BIOS config */
5009 err = alc861_parse_auto_config(codec);
5010 if (err < 0) {
5011 alc_free(codec);
5012 return err;
5013 }
5014#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5015 else if (!err) {
5016 printk(KERN_INFO
5017 "hda_codec: Cannot set up configuration "
5018 "from BIOS. Using base mode...\n");
5019 board_config = ALC861_3ST_DIG;
5020 }
5021#endif
5022 }
5023
Takashi Iwai1d045db2011-07-07 18:23:21 +02005024 if (board_config != ALC_MODEL_AUTO)
5025 setup_preset(codec, &alc861_presets[board_config]);
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)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005034 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005035
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, 0x23, 0, HDA_OUTPUT);
5043 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005044
5045 spec->vmaster_nid = 0x03;
5046
5047 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5048
5049 codec->patch_ops = alc_patch_ops;
5050 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02005051 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005052#ifdef CONFIG_SND_HDA_POWER_SAVE
5053 spec->power_hook = alc_power_eapd;
5054#endif
5055 }
5056#ifdef CONFIG_SND_HDA_POWER_SAVE
5057 if (!spec->loopback.amplist)
5058 spec->loopback.amplist = alc861_loopbacks;
5059#endif
5060
5061 return 0;
5062}
5063
5064/*
5065 * ALC861-VD support
5066 *
5067 * Based on ALC882
5068 *
5069 * In addition, an independent DAC
5070 */
5071#ifdef CONFIG_SND_HDA_POWER_SAVE
5072#define alc861vd_loopbacks alc880_loopbacks
5073#endif
5074
Takashi Iwai1d045db2011-07-07 18:23:21 +02005075static int alc861vd_parse_auto_config(struct hda_codec *codec)
5076{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005077 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005078 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5079 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005080}
5081
Takashi Iwai1d045db2011-07-07 18:23:21 +02005082enum {
5083 ALC660VD_FIX_ASUS_GPIO1
5084};
5085
5086/* reset GPIO1 */
5087static const struct alc_fixup alc861vd_fixups[] = {
5088 [ALC660VD_FIX_ASUS_GPIO1] = {
5089 .type = ALC_FIXUP_VERBS,
5090 .v.verbs = (const struct hda_verb[]) {
5091 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5092 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5093 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5094 { }
5095 }
5096 },
5097};
5098
5099static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
5100 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
5101 {}
5102};
5103
5104static const struct hda_verb alc660vd_eapd_verbs[] = {
5105 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
5106 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
5107 { }
5108};
5109
5110/*
5111 */
5112#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5113#include "alc861vd_quirks.c"
5114#endif
5115
5116static int patch_alc861vd(struct hda_codec *codec)
5117{
5118 struct alc_spec *spec;
5119 int err, board_config;
5120
5121 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5122 if (spec == NULL)
5123 return -ENOMEM;
5124
5125 codec->spec = spec;
5126
5127 spec->mixer_nid = 0x0b;
5128
5129 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
5130 alc861vd_models, alc861vd_cfg_tbl);
5131
5132 if (board_config < 0) {
5133 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5134 codec->chip_name);
5135 board_config = ALC_MODEL_AUTO;
5136 }
5137
5138 if (board_config == ALC_MODEL_AUTO) {
5139 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
5140 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5141 }
5142
5143 if (board_config == ALC_MODEL_AUTO) {
5144 /* automatic parse from the BIOS config */
5145 err = alc861vd_parse_auto_config(codec);
5146 if (err < 0) {
5147 alc_free(codec);
5148 return err;
5149 }
5150#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5151 else if (!err) {
5152 printk(KERN_INFO
5153 "hda_codec: Cannot set up configuration "
5154 "from BIOS. Using base mode...\n");
5155 board_config = ALC861VD_3ST;
5156 }
5157#endif
5158 }
5159
Takashi Iwai1d045db2011-07-07 18:23:21 +02005160 if (board_config != ALC_MODEL_AUTO)
5161 setup_preset(codec, &alc861vd_presets[board_config]);
5162
5163 if (codec->vendor_id == 0x10ec0660) {
5164 /* always turn on EAPD */
5165 add_verb(spec, alc660vd_eapd_verbs);
5166 }
5167
Takashi Iwai60a6a842011-07-27 14:01:24 +02005168 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005169 alc_auto_fill_adc_caps(codec);
5170 alc_rebuild_imux_for_auto_mic(codec);
5171 alc_remove_invalid_adc_nids(codec);
5172 }
5173
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005174 if (!spec->no_analog && !spec->cap_mixer)
5175 set_capture_mixer(codec);
5176
5177 if (!spec->no_analog) {
5178 err = snd_hda_attach_beep_device(codec, 0x23);
5179 if (err < 0) {
5180 alc_free(codec);
5181 return err;
5182 }
5183 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5184 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005185
5186 spec->vmaster_nid = 0x02;
5187
5188 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5189
5190 codec->patch_ops = alc_patch_ops;
5191
5192 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005193 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005194 spec->shutup = alc_eapd_shutup;
5195#ifdef CONFIG_SND_HDA_POWER_SAVE
5196 if (!spec->loopback.amplist)
5197 spec->loopback.amplist = alc861vd_loopbacks;
5198#endif
5199
5200 return 0;
5201}
5202
5203/*
5204 * ALC662 support
5205 *
5206 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5207 * configuration. Each pin widget can choose any input DACs and a mixer.
5208 * Each ADC is connected from a mixer of all inputs. This makes possible
5209 * 6-channel independent captures.
5210 *
5211 * In addition, an independent DAC for the multi-playback (not used in this
5212 * driver yet).
5213 */
5214#ifdef CONFIG_SND_HDA_POWER_SAVE
5215#define alc662_loopbacks alc880_loopbacks
5216#endif
5217
5218/*
5219 * BIOS auto configuration
5220 */
5221
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005222static int alc662_parse_auto_config(struct hda_codec *codec)
5223{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005224 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005225 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5226 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5227 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005228
Kailang Yang6227cdc2010-02-25 08:36:52 +01005229 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5230 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005231 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005232 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005233 ssids = alc662_ssids;
5234 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005235}
5236
Todd Broch6be79482010-12-07 16:51:05 -08005237static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005238 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005239{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005240 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005241 return;
Todd Broch6be79482010-12-07 16:51:05 -08005242 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5243 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5244 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5245 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5246 (0 << AC_AMPCAP_MUTE_SHIFT)))
5247 printk(KERN_WARNING
5248 "hda_codec: failed to override amp caps for NID 0x2\n");
5249}
5250
David Henningsson6cb3b702010-09-09 08:51:44 +02005251enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005252 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005253 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005254 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005255 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005256 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005257 ALC662_FIXUP_HP_RP5800,
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005258 ALC662_FIXUP_ECS,
David Henningsson6cb3b702010-09-09 08:51:44 +02005259};
5260
5261static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005262 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005263 .type = ALC_FIXUP_PINS,
5264 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005265 { 0x15, 0x99130112 }, /* subwoofer */
5266 { }
5267 }
5268 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005269 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005270 .type = ALC_FIXUP_PINS,
5271 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005272 { 0x17, 0x99130112 }, /* subwoofer */
5273 { }
5274 }
5275 },
Todd Broch6be79482010-12-07 16:51:05 -08005276 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005277 .type = ALC_FIXUP_FUNC,
5278 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005279 },
5280 [ALC662_FIXUP_CZC_P10T] = {
5281 .type = ALC_FIXUP_VERBS,
5282 .v.verbs = (const struct hda_verb[]) {
5283 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5284 {}
5285 }
5286 },
David Henningsson94024cd2011-04-29 14:10:55 +02005287 [ALC662_FIXUP_SKU_IGNORE] = {
5288 .type = ALC_FIXUP_SKU,
5289 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005290 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005291 [ALC662_FIXUP_HP_RP5800] = {
5292 .type = ALC_FIXUP_PINS,
5293 .v.pins = (const struct alc_pincfg[]) {
5294 { 0x14, 0x0221201f }, /* HP out */
5295 { }
5296 },
5297 .chained = true,
5298 .chain_id = ALC662_FIXUP_SKU_IGNORE
5299 },
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005300 [ALC662_FIXUP_ECS] = {
5301 .type = ALC_FIXUP_PINS,
5302 .v.pins = (const struct alc_pincfg[]) {
5303 { 0x14, 0x99130110 }, /* speaker */
5304 { 0x18, 0x01a19820 }, /* mic */
5305 { 0x19, 0x99a3092f }, /* int-mic */
5306 { 0x1b, 0x0121401f }, /* HP out */
5307 { }
5308 },
5309 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005310};
5311
Takashi Iwaia9111322011-05-02 11:30:18 +02005312static const struct snd_pci_quirk alc662_fixup_tbl[] = {
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005313 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ECS),
David Henningssona6c47a82011-02-10 15:39:19 +01005314 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005315 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005316 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005317 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005318 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ECS),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005319 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005320 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005321 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005322 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02005323 {}
5324};
5325
Todd Broch6be79482010-12-07 16:51:05 -08005326static const struct alc_model_fixup alc662_fixup_models[] = {
5327 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
5328 {}
5329};
David Henningsson6cb3b702010-09-09 08:51:44 +02005330
5331
Takashi Iwai1d045db2011-07-07 18:23:21 +02005332/*
5333 */
5334#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5335#include "alc662_quirks.c"
5336#endif
5337
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005338static int patch_alc662(struct hda_codec *codec)
5339{
5340 struct alc_spec *spec;
5341 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02005342 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005343
5344 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5345 if (!spec)
5346 return -ENOMEM;
5347
5348 codec->spec = spec;
5349
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005350 spec->mixer_nid = 0x0b;
5351
Kailang Yangda00c242010-03-19 11:23:45 +01005352 alc_auto_parse_customize_define(codec);
5353
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005354 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5355
Kailang Yang693194f2010-10-21 08:51:48 +02005356 coef = alc_read_coef_idx(codec, 0);
5357 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005358 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005359 else if (coef & (1 << 14) &&
5360 codec->bus->pci->subsystem_vendor == 0x1025 &&
5361 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005362 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005363 else if (coef == 0x4011)
5364 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005365
Takashi Iwai1d045db2011-07-07 18:23:21 +02005366 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
5367 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005368 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005369 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5370 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005371 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005372 }
5373
Takashi Iwai1d045db2011-07-07 18:23:21 +02005374 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005375 alc_pick_fixup(codec, alc662_fixup_models,
5376 alc662_fixup_tbl, alc662_fixups);
5377 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005378 /* automatic parse from the BIOS config */
5379 err = alc662_parse_auto_config(codec);
5380 if (err < 0) {
5381 alc_free(codec);
5382 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005383 }
5384#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5385 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005386 printk(KERN_INFO
5387 "hda_codec: Cannot set up configuration "
5388 "from BIOS. Using base mode...\n");
5389 board_config = ALC662_3ST_2ch_DIG;
5390 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005391#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005392 }
5393
Takashi Iwai1d045db2011-07-07 18:23:21 +02005394 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005395 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005396
Takashi Iwai60a6a842011-07-27 14:01:24 +02005397 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005398 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005399 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005400 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005401 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005402
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005403 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005404 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005405
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005406 if (!spec->no_analog && has_cdefine_beep(codec)) {
5407 err = snd_hda_attach_beep_device(codec, 0x1);
5408 if (err < 0) {
5409 alc_free(codec);
5410 return err;
5411 }
Kailang Yangda00c242010-03-19 11:23:45 +01005412 switch (codec->vendor_id) {
5413 case 0x10ec0662:
5414 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5415 break;
5416 case 0x10ec0272:
5417 case 0x10ec0663:
5418 case 0x10ec0665:
5419 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5420 break;
5421 case 0x10ec0273:
5422 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5423 break;
5424 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005425 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005426 spec->vmaster_nid = 0x02;
5427
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005428 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5429
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005430 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005431 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005432 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c716152011-04-07 10:37:16 +02005433 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005434
Kailang Yangbf1b0222010-10-21 08:49:56 +02005435 alc_init_jacks(codec);
5436
Takashi Iwaicb53c622007-08-10 17:21:45 +02005437#ifdef CONFIG_SND_HDA_POWER_SAVE
5438 if (!spec->loopback.amplist)
5439 spec->loopback.amplist = alc662_loopbacks;
5440#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005441
5442 return 0;
5443}
5444
Kailang Yang274693f2009-12-03 10:07:50 +01005445static int patch_alc888(struct hda_codec *codec)
5446{
5447 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5448 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005449 if (codec->vendor_id == 0x10ec0887)
5450 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5451 else
5452 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005453 if (!codec->chip_name) {
5454 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005455 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005456 }
5457 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005458 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005459 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005460}
5461
Kailang Yangb478b992011-05-18 11:51:15 +02005462static int patch_alc899(struct hda_codec *codec)
5463{
5464 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5465 kfree(codec->chip_name);
5466 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5467 }
5468 return patch_alc882(codec);
5469}
5470
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005471/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005472 * ALC680 support
5473 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005474
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005475static int alc680_parse_auto_config(struct hda_codec *codec)
5476{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005477 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005478}
5479
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005480/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005481 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005482static int patch_alc680(struct hda_codec *codec)
5483{
5484 struct alc_spec *spec;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005485 int err;
5486
5487 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5488 if (spec == NULL)
5489 return -ENOMEM;
5490
5491 codec->spec = spec;
5492
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005493 /* ALC680 has no aa-loopback mixer */
5494
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02005495 /* automatic parse from the BIOS config */
5496 err = alc680_parse_auto_config(codec);
5497 if (err < 0) {
5498 alc_free(codec);
5499 return err;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005500 }
5501
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005502 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005503 set_capture_mixer(codec);
5504
5505 spec->vmaster_nid = 0x02;
5506
5507 codec->patch_ops = alc_patch_ops;
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02005508 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005509
5510 return 0;
5511}
5512
5513/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514 * patch entries
5515 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005516static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005517 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005519 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005520 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005521 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005522 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005523 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005524 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005525 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005526 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005527 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005528 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005529 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5530 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5531 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005532 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +02005533 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005534 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5535 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005536 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005537 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005538 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005539 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005540 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005541 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +02005542 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005543 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005544 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005545 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005546 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005547 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005548 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005549 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +02005550 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005551 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai49535502009-06-30 15:28:30 +02005552 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005553 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005554 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555 {} /* terminator */
5556};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005557
5558MODULE_ALIAS("snd-hda-codec-id:10ec*");
5559
5560MODULE_LICENSE("GPL");
5561MODULE_DESCRIPTION("Realtek HD-audio codec");
5562
5563static struct hda_codec_preset_list realtek_list = {
5564 .preset = snd_hda_preset_realtek,
5565 .owner = THIS_MODULE,
5566};
5567
5568static int __init patch_realtek_init(void)
5569{
5570 return snd_hda_add_codec_preset(&realtek_list);
5571}
5572
5573static void __exit patch_realtek_exit(void)
5574{
5575 snd_hda_delete_codec_preset(&realtek_list);
5576}
5577
5578module_init(patch_realtek_init)
5579module_exit(patch_realtek_exit)