blob: d330e9717432ec7e0ed5714c33fb49dd82399ee0 [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];
Kailang Yangdf694da2005-12-05 19:42:22 +0100206};
207
Takashi Iwai1d045db2011-07-07 18:23:21 +0200208#define ALC_MODEL_AUTO 0 /* common for all chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
Takashi Iwai44c02402011-07-08 15:14:19 +0200210static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
211 int dir, unsigned int bits)
212{
213 if (!nid)
214 return false;
215 if (get_wcaps(codec, nid) & (1 << (dir + 1)))
216 if (query_amp_caps(codec, nid, dir) & bits)
217 return true;
218 return false;
219}
220
221#define nid_has_mute(codec, nid, dir) \
222 check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
223#define nid_has_volume(codec, nid, dir) \
224 check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226/*
227 * input MUX handling
228 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200229static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
230 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231{
232 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
233 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200234 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
235 if (mux_idx >= spec->num_mux_defs)
236 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100237 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
238 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200239 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240}
241
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200242static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
243 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244{
245 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
246 struct alc_spec *spec = codec->spec;
247 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
248
249 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
250 return 0;
251}
252
Takashi Iwai21268962011-07-07 15:01:13 +0200253static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254{
Takashi Iwai21268962011-07-07 15:01:13 +0200255 struct alc_spec *spec = codec->spec;
256 hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
257
258 if (spec->cur_adc && spec->cur_adc != new_adc) {
259 /* stream is running, let's swap the current ADC */
260 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
261 spec->cur_adc = new_adc;
262 snd_hda_codec_setup_stream(codec, new_adc,
263 spec->cur_adc_stream_tag, 0,
264 spec->cur_adc_format);
265 return true;
266 }
267 return false;
268}
269
270/* select the given imux item; either unmute exclusively or select the route */
271static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
272 unsigned int idx, bool force)
273{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100275 const struct hda_input_mux *imux;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100276 unsigned int mux_idx;
Takashi Iwai21268962011-07-07 15:01:13 +0200277 int i, type;
278 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Takashi Iwaicd896c32008-11-18 12:36:33 +0100280 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
281 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100282 if (!imux->num_items && mux_idx > 0)
283 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100284
Takashi Iwai21268962011-07-07 15:01:13 +0200285 if (idx >= imux->num_items)
286 idx = imux->num_items - 1;
287 if (spec->cur_mux[adc_idx] == idx && !force)
288 return 0;
289 spec->cur_mux[adc_idx] = idx;
290
291 if (spec->dyn_adc_switch) {
292 alc_dyn_adc_pcm_resetup(codec, idx);
293 adc_idx = spec->dyn_adc_idx[idx];
294 }
295
296 nid = spec->capsrc_nids ?
297 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
298
299 /* no selection? */
300 if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
301 return 1;
302
Takashi Iwaia22d5432009-07-27 12:54:26 +0200303 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200304 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100305 /* Matrix-mixer style (e.g. ALC882) */
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100306 for (i = 0; i < imux->num_items; i++) {
307 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
308 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
309 imux->items[i].index,
310 HDA_AMP_MUTE, v);
311 }
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100312 } else {
313 /* MUX style (e.g. ALC880) */
Takashi Iwai21268962011-07-07 15:01:13 +0200314 snd_hda_codec_write_cache(codec, nid, 0,
315 AC_VERB_SET_CONNECT_SEL,
316 imux->items[idx].index);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100317 }
Takashi Iwai21268962011-07-07 15:01:13 +0200318 return 1;
319}
320
321static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
322 struct snd_ctl_elem_value *ucontrol)
323{
324 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
325 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
326 return alc_mux_select(codec, adc_idx,
327 ucontrol->value.enumerated.item[0], false);
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100328}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200329
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100331 * set up the input pin config (depending on the given auto-pin type)
332 */
333static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
334 int auto_pin_type)
335{
336 unsigned int val = PIN_IN;
337
Takashi Iwai86e29592010-09-09 14:50:17 +0200338 if (auto_pin_type == AUTO_PIN_MIC) {
Takashi Iwai23f0c042009-02-26 13:03:58 +0100339 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200340 unsigned int oldval;
341 oldval = snd_hda_codec_read(codec, nid, 0,
342 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100343 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100344 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200345 /* if the default pin setup is vref50, we give it priority */
346 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100347 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200348 else if (pincap & AC_PINCAP_VREF_50)
349 val = PIN_VREF50;
350 else if (pincap & AC_PINCAP_VREF_100)
351 val = PIN_VREF100;
352 else if (pincap & AC_PINCAP_VREF_GRD)
353 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100354 }
355 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
356}
357
358/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200359 * Append the given mixer and verb elements for the later use
360 * The mixer array is referred in build_controls(), and init_verbs are
361 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100362 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200363static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100364{
365 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
366 return;
367 spec->mixers[spec->num_mixers++] = mix;
368}
369
370static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
371{
372 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
373 return;
374 spec->init_verbs[spec->num_init_verbs++] = verb;
375}
376
377/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200378 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100379 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200380/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200381static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200382 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
383 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
384 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
385 { }
386};
387
Takashi Iwaia9111322011-05-02 11:30:18 +0200388static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200389 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
390 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
391 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
392 { }
393};
394
Takashi Iwaia9111322011-05-02 11:30:18 +0200395static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200396 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
397 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
398 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
399 { }
400};
401
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200402/*
403 * Fix hardware PLL issue
404 * On some codecs, the analog PLL gating control must be off while
405 * the default value is 1.
406 */
407static void alc_fix_pll(struct hda_codec *codec)
408{
409 struct alc_spec *spec = codec->spec;
410 unsigned int val;
411
412 if (!spec->pll_nid)
413 return;
414 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
415 spec->pll_coef_idx);
416 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
417 AC_VERB_GET_PROC_COEF, 0);
418 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
419 spec->pll_coef_idx);
420 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
421 val & ~(1 << spec->pll_coef_bit));
422}
423
424static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
425 unsigned int coef_idx, unsigned int coef_bit)
426{
427 struct alc_spec *spec = codec->spec;
428 spec->pll_nid = nid;
429 spec->pll_coef_idx = coef_idx;
430 spec->pll_coef_bit = coef_bit;
431 alc_fix_pll(codec);
432}
433
Takashi Iwai1d045db2011-07-07 18:23:21 +0200434/*
435 * Jack-reporting via input-jack layer
436 */
437
438/* initialization of jacks; currently checks only a few known pins */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200439static int alc_init_jacks(struct hda_codec *codec)
440{
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100441#ifdef CONFIG_SND_HDA_INPUT_JACK
Kailang Yang9ad0e492010-09-14 23:22:00 +0200442 struct alc_spec *spec = codec->spec;
443 int err;
444 unsigned int hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai21268962011-07-07 15:01:13 +0200445 unsigned int mic_nid = spec->ext_mic_pin;
446 unsigned int dock_nid = spec->dock_mic_pin;
Kailang Yang9ad0e492010-09-14 23:22:00 +0200447
Takashi Iwai265a0242010-09-21 11:26:21 +0200448 if (hp_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100449 err = snd_hda_input_jack_add(codec, hp_nid,
450 SND_JACK_HEADPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200451 if (err < 0)
452 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100453 snd_hda_input_jack_report(codec, hp_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200454 }
Kailang Yang9ad0e492010-09-14 23:22:00 +0200455
Takashi Iwai265a0242010-09-21 11:26:21 +0200456 if (mic_nid) {
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100457 err = snd_hda_input_jack_add(codec, mic_nid,
458 SND_JACK_MICROPHONE, NULL);
Takashi Iwai265a0242010-09-21 11:26:21 +0200459 if (err < 0)
460 return err;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100461 snd_hda_input_jack_report(codec, mic_nid);
Takashi Iwai265a0242010-09-21 11:26:21 +0200462 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +0200463 if (dock_nid) {
464 err = snd_hda_input_jack_add(codec, dock_nid,
465 SND_JACK_MICROPHONE, NULL);
466 if (err < 0)
467 return err;
468 snd_hda_input_jack_report(codec, dock_nid);
469 }
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100470#endif /* CONFIG_SND_HDA_INPUT_JACK */
Kailang Yang9ad0e492010-09-14 23:22:00 +0200471 return 0;
472}
Kailang Yang9ad0e492010-09-14 23:22:00 +0200473
Takashi Iwai1d045db2011-07-07 18:23:21 +0200474/*
475 * Jack detections for HP auto-mute and mic-switch
476 */
477
478/* check each pin in the given array; returns true if any of them is plugged */
479static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
Kailang Yangc9b58002007-10-16 14:30:01 +0200480{
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200481 int i, present = 0;
Kailang Yangc9b58002007-10-16 14:30:01 +0200482
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200483 for (i = 0; i < num_pins; i++) {
484 hda_nid_t nid = pins[i];
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200485 if (!nid)
486 break;
Takashi Iwaicd372fb2011-03-03 14:40:14 +0100487 snd_hda_input_jack_report(codec, nid);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200488 present |= snd_hda_jack_detect(codec, nid);
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200489 }
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200490 return present;
491}
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200492
Takashi Iwai1d045db2011-07-07 18:23:21 +0200493/* standard HP/line-out auto-mute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200494static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
Takashi Iwaie9427962011-04-28 15:46:07 +0200495 bool mute, bool hp_out)
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200496{
497 struct alc_spec *spec = codec->spec;
498 unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
Takashi Iwaie9427962011-04-28 15:46:07 +0200499 unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200500 int i;
501
502 for (i = 0; i < num_pins; i++) {
503 hda_nid_t nid = pins[i];
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200504 if (!nid)
505 break;
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200506 switch (spec->automute_mode) {
507 case ALC_AUTOMUTE_PIN:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200508 snd_hda_codec_write(codec, nid, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200509 AC_VERB_SET_PIN_WIDGET_CONTROL,
510 pin_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200511 break;
512 case ALC_AUTOMUTE_AMP:
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200513 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200514 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200515 break;
516 case ALC_AUTOMUTE_MIXER:
517 nid = spec->automute_mixer_nid[i];
518 if (!nid)
519 break;
520 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200521 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200522 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200523 HDA_AMP_MUTE, mute_bits);
Takashi Iwai3b8510c2011-04-28 14:03:24 +0200524 break;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200525 }
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200526 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200527}
528
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200529/* Toggle internal speakers muting */
530static void update_speakers(struct hda_codec *codec)
531{
532 struct alc_spec *spec = codec->spec;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200533 int on;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200534
Takashi Iwaic0a20262011-06-10 15:28:15 +0200535 /* Control HP pins/amps depending on master_mute state;
536 * in general, HP pins/amps control should be enabled in all cases,
537 * but currently set only for master_mute, just to be safe
538 */
539 do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
540 spec->autocfg.hp_pins, spec->master_mute, true);
541
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200542 if (!spec->automute)
543 on = 0;
544 else
545 on = spec->jack_present | spec->line_jack_present;
546 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200547 do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200548 spec->autocfg.speaker_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200549
550 /* toggle line-out mutes if needed, too */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200551 /* if LO is a copy of either HP or Speaker, don't need to handle it */
552 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
553 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200554 return;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200555 if (!spec->automute_lines || !spec->automute)
556 on = 0;
557 else
558 on = spec->jack_present;
559 on |= spec->master_mute;
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200560 do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200561 spec->autocfg.line_out_pins, on, false);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200562}
563
Takashi Iwai24519912011-08-16 15:08:49 +0200564static void call_update_speakers(struct hda_codec *codec)
565{
566 struct alc_spec *spec = codec->spec;
567 if (spec->automute_hook)
568 spec->automute_hook(codec);
569 else
570 update_speakers(codec);
571}
572
Takashi Iwai1d045db2011-07-07 18:23:21 +0200573/* standard HP-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200574static void alc_hp_automute(struct hda_codec *codec)
575{
576 struct alc_spec *spec = codec->spec;
577
578 if (!spec->automute)
579 return;
580 spec->jack_present =
581 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
582 spec->autocfg.hp_pins);
Takashi Iwai24519912011-08-16 15:08:49 +0200583 call_update_speakers(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200584}
585
Takashi Iwai1d045db2011-07-07 18:23:21 +0200586/* standard line-out-automute helper */
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200587static void alc_line_automute(struct hda_codec *codec)
588{
589 struct alc_spec *spec = codec->spec;
590
591 if (!spec->automute || !spec->detect_line)
592 return;
593 spec->line_jack_present =
594 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
595 spec->autocfg.line_out_pins);
Takashi Iwai24519912011-08-16 15:08:49 +0200596 call_update_speakers(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200597}
598
Takashi Iwai8d087c72011-06-28 12:45:47 +0200599#define get_connection_index(codec, mux, nid) \
600 snd_hda_get_conn_index(codec, mux, nid, 0)
Takashi Iwai6c819492009-08-10 18:47:44 +0200601
Takashi Iwai1d045db2011-07-07 18:23:21 +0200602/* standard mic auto-switch helper */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200603static void alc_mic_automute(struct hda_codec *codec)
604{
605 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +0200606 hda_nid_t *pins = spec->imux_pins;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200607
Takashi Iwai21268962011-07-07 15:01:13 +0200608 if (!spec->auto_mic || !spec->auto_mic_valid_imux)
Takashi Iwai6c819492009-08-10 18:47:44 +0200609 return;
610 if (snd_BUG_ON(!spec->adc_nids))
611 return;
Takashi Iwai21268962011-07-07 15:01:13 +0200612 if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
Takashi Iwai840b64c2010-07-13 22:49:01 +0200613 return;
Takashi Iwai840b64c2010-07-13 22:49:01 +0200614
Takashi Iwai21268962011-07-07 15:01:13 +0200615 if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
616 alc_mux_select(codec, 0, spec->ext_mic_idx, false);
617 else if (spec->dock_mic_idx >= 0 &&
618 snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
619 alc_mux_select(codec, 0, spec->dock_mic_idx, false);
620 else
621 alc_mux_select(codec, 0, spec->int_mic_idx, false);
Takashi Iwai6c819492009-08-10 18:47:44 +0200622
Takashi Iwai21268962011-07-07 15:01:13 +0200623 snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
624 if (spec->dock_mic_idx >= 0)
625 snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200626}
627
Kailang Yangc9b58002007-10-16 14:30:01 +0200628/* unsolicited event for HP jack sensing */
629static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
630{
631 if (codec->vendor_id == 0x10ec0880)
632 res >>= 28;
633 else
634 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200635 switch (res) {
Takashi Iwai1d045db2011-07-07 18:23:21 +0200636 case ALC_HP_EVENT:
Takashi Iwaid922b512011-04-28 12:18:53 +0200637 alc_hp_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200638 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200639 case ALC_FRONT_EVENT:
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200640 alc_line_automute(codec);
641 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200642 case ALC_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +0200643 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200644 break;
645 }
Kailang Yang7fb0d782008-10-15 11:12:35 +0200646}
647
Takashi Iwai1d045db2011-07-07 18:23:21 +0200648/* call init functions of standard auto-mute helpers */
Kailang Yang7fb0d782008-10-15 11:12:35 +0200649static void alc_inithook(struct hda_codec *codec)
650{
Takashi Iwaid922b512011-04-28 12:18:53 +0200651 alc_hp_automute(codec);
Takashi Iwaie6a5e1b2011-04-28 14:41:52 +0200652 alc_line_automute(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +0200653 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200654}
655
Kailang Yangf9423e72008-05-27 12:32:25 +0200656/* additional initialization for ALC888 variants */
657static void alc888_coef_init(struct hda_codec *codec)
658{
659 unsigned int tmp;
660
661 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
662 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
663 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100664 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200665 /* alc888S-VC */
666 snd_hda_codec_read(codec, 0x20, 0,
667 AC_VERB_SET_PROC_COEF, 0x830);
668 else
669 /* alc888-VB */
670 snd_hda_codec_read(codec, 0x20, 0,
671 AC_VERB_SET_PROC_COEF, 0x3030);
672}
673
Takashi Iwai1d045db2011-07-07 18:23:21 +0200674/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200675static void alc889_coef_init(struct hda_codec *codec)
676{
677 unsigned int tmp;
678
679 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
680 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
681 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
682 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
683}
684
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100685/* turn on/off EAPD control (only if available) */
686static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
687{
688 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
689 return;
690 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
691 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
692 on ? 2 : 0);
693}
694
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200695/* turn on/off EAPD controls of the codec */
696static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
697{
698 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200699 static hda_nid_t pins[] = {
700 0x0f, 0x10, 0x14, 0x15, 0
701 };
702 hda_nid_t *p;
703 for (p = pins; *p; p++)
704 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200705}
706
Takashi Iwai1c716152011-04-07 10:37:16 +0200707/* generic shutup callback;
708 * just turning off EPAD and a little pause for avoiding pop-noise
709 */
710static void alc_eapd_shutup(struct hda_codec *codec)
711{
712 alc_auto_setup_eapd(codec, false);
713 msleep(200);
714}
715
Takashi Iwai1d045db2011-07-07 18:23:21 +0200716/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200717static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200718{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200719 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200720
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200721 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200722 switch (type) {
723 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200724 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
725 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200726 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200727 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
728 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200729 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200730 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
731 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200732 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200733 switch (codec->vendor_id) {
734 case 0x10ec0260:
735 snd_hda_codec_write(codec, 0x1a, 0,
736 AC_VERB_SET_COEF_INDEX, 7);
737 tmp = snd_hda_codec_read(codec, 0x1a, 0,
738 AC_VERB_GET_PROC_COEF, 0);
739 snd_hda_codec_write(codec, 0x1a, 0,
740 AC_VERB_SET_COEF_INDEX, 7);
741 snd_hda_codec_write(codec, 0x1a, 0,
742 AC_VERB_SET_PROC_COEF,
743 tmp | 0x2010);
744 break;
745 case 0x10ec0262:
746 case 0x10ec0880:
747 case 0x10ec0882:
748 case 0x10ec0883:
749 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100750 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100751 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200752 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200753 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200754 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200755 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200756 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100757#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200758 case 0x10ec0267:
759 case 0x10ec0268:
760 snd_hda_codec_write(codec, 0x20, 0,
761 AC_VERB_SET_COEF_INDEX, 7);
762 tmp = snd_hda_codec_read(codec, 0x20, 0,
763 AC_VERB_GET_PROC_COEF, 0);
764 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200765 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200766 snd_hda_codec_write(codec, 0x20, 0,
767 AC_VERB_SET_PROC_COEF,
768 tmp | 0x3000);
769 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100770#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200771 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200772 break;
773 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200774}
Kailang Yangea1fb292008-08-26 12:58:38 +0200775
Takashi Iwai1d045db2011-07-07 18:23:21 +0200776/*
777 * Auto-Mute mode mixer enum support
778 */
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200779static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
780 struct snd_ctl_elem_info *uinfo)
781{
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200782 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
783 struct alc_spec *spec = codec->spec;
784 static const char * const texts2[] = {
785 "Disabled", "Enabled"
786 };
787 static const char * const texts3[] = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200788 "Disabled", "Speaker Only", "Line-Out+Speaker"
789 };
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200790 const char * const *texts;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200791
792 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
793 uinfo->count = 1;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200794 if (spec->automute_hp_lo) {
795 uinfo->value.enumerated.items = 3;
796 texts = texts3;
797 } else {
798 uinfo->value.enumerated.items = 2;
799 texts = texts2;
800 }
801 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
802 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200803 strcpy(uinfo->value.enumerated.name,
804 texts[uinfo->value.enumerated.item]);
805 return 0;
806}
807
808static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
809 struct snd_ctl_elem_value *ucontrol)
810{
811 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
812 struct alc_spec *spec = codec->spec;
813 unsigned int val;
814 if (!spec->automute)
815 val = 0;
816 else if (!spec->automute_lines)
817 val = 1;
818 else
819 val = 2;
820 ucontrol->value.enumerated.item[0] = val;
821 return 0;
822}
823
824static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
825 struct snd_ctl_elem_value *ucontrol)
826{
827 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
828 struct alc_spec *spec = codec->spec;
829
830 switch (ucontrol->value.enumerated.item[0]) {
831 case 0:
832 if (!spec->automute)
833 return 0;
834 spec->automute = 0;
835 break;
836 case 1:
837 if (spec->automute && !spec->automute_lines)
838 return 0;
839 spec->automute = 1;
840 spec->automute_lines = 0;
841 break;
842 case 2:
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200843 if (!spec->automute_hp_lo)
844 return -EINVAL;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200845 if (spec->automute && spec->automute_lines)
846 return 0;
847 spec->automute = 1;
848 spec->automute_lines = 1;
849 break;
850 default:
851 return -EINVAL;
852 }
Takashi Iwai24519912011-08-16 15:08:49 +0200853 call_update_speakers(codec);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200854 return 1;
855}
856
Takashi Iwaia9111322011-05-02 11:30:18 +0200857static const struct snd_kcontrol_new alc_automute_mode_enum = {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200858 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
859 .name = "Auto-Mute Mode",
860 .info = alc_automute_mode_info,
861 .get = alc_automute_mode_get,
862 .put = alc_automute_mode_put,
863};
864
Takashi Iwai1d045db2011-07-07 18:23:21 +0200865static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
866{
867 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
868 return snd_array_new(&spec->kctls);
869}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200870
871static int alc_add_automute_mode_enum(struct hda_codec *codec)
872{
873 struct alc_spec *spec = codec->spec;
874 struct snd_kcontrol_new *knew;
875
876 knew = alc_kcontrol_new(spec);
877 if (!knew)
878 return -ENOMEM;
879 *knew = alc_automute_mode_enum;
880 knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
881 if (!knew->name)
882 return -ENOMEM;
883 return 0;
884}
885
Takashi Iwai1d045db2011-07-07 18:23:21 +0200886/*
887 * Check the availability of HP/line-out auto-mute;
888 * Set up appropriately if really supported
889 */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200890static void alc_init_auto_hp(struct hda_codec *codec)
891{
892 struct alc_spec *spec = codec->spec;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200893 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200894 int present = 0;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200895 int i;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200896
Takashi Iwai1daf5f42011-04-28 17:57:46 +0200897 if (cfg->hp_pins[0])
898 present++;
899 if (cfg->line_out_pins[0])
900 present++;
901 if (cfg->speaker_pins[0])
902 present++;
903 if (present < 2) /* need two different output types */
904 return;
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200905 if (present == 3)
906 spec->automute_hp_lo = 1; /* both HP and LO automute */
Kailang Yangc9b58002007-10-16 14:30:01 +0200907
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200908 if (!cfg->speaker_pins[0] &&
909 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200910 memcpy(cfg->speaker_pins, cfg->line_out_pins,
911 sizeof(cfg->speaker_pins));
912 cfg->speaker_outs = cfg->line_outs;
913 }
914
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200915 if (!cfg->hp_pins[0] &&
916 cfg->line_out_type == AUTO_PIN_HP_OUT) {
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200917 memcpy(cfg->hp_pins, cfg->line_out_pins,
918 sizeof(cfg->hp_pins));
919 cfg->hp_outs = cfg->line_outs;
920 }
921
922 for (i = 0; i < cfg->hp_outs; i++) {
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200923 hda_nid_t nid = cfg->hp_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200924 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200925 continue;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200926 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200927 nid);
928 snd_hda_codec_write_cache(codec, nid, 0,
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200929 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200930 AC_USRSP_EN | ALC_HP_EVENT);
Takashi Iwaid922b512011-04-28 12:18:53 +0200931 spec->automute = 1;
932 spec->automute_mode = ALC_AUTOMUTE_PIN;
Takashi Iwaibb35feb2010-09-08 15:30:49 +0200933 }
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200934 if (spec->automute && cfg->line_out_pins[0] &&
Takashi Iwaic48a8fb2011-07-27 16:41:57 +0200935 cfg->speaker_pins[0] &&
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200936 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
937 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
938 for (i = 0; i < cfg->line_outs; i++) {
939 hda_nid_t nid = cfg->line_out_pins[i];
Takashi Iwai06dec222011-05-17 10:00:16 +0200940 if (!is_jack_detectable(codec, nid))
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200941 continue;
942 snd_printdd("realtek: Enable Line-Out auto-muting "
943 "on NID 0x%x\n", nid);
944 snd_hda_codec_write_cache(codec, nid, 0,
945 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +0200946 AC_USRSP_EN | ALC_FRONT_EVENT);
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200947 spec->detect_line = 1;
948 }
Takashi Iwai52d3cb82011-05-17 10:04:08 +0200949 spec->automute_lines = spec->detect_line;
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200950 }
Takashi Iwaiae8a60a2011-04-28 18:09:52 +0200951
952 if (spec->automute) {
953 /* create a control for automute mode */
954 alc_add_automute_mode_enum(codec);
955 spec->unsol_event = alc_sku_unsol_event;
956 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200957}
958
Takashi Iwai1d045db2011-07-07 18:23:21 +0200959/* return the position of NID in the list, or -1 if not found */
Takashi Iwai21268962011-07-07 15:01:13 +0200960static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
961{
962 int i;
963 for (i = 0; i < nums; i++)
964 if (list[i] == nid)
965 return i;
966 return -1;
967}
968
Takashi Iwai1d045db2011-07-07 18:23:21 +0200969/* check whether dynamic ADC-switching is available */
970static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
971{
972 struct alc_spec *spec = codec->spec;
973 struct hda_input_mux *imux = &spec->private_imux[0];
974 int i, n, idx;
975 hda_nid_t cap, pin;
976
977 if (imux != spec->input_mux) /* no dynamic imux? */
978 return false;
979
980 for (n = 0; n < spec->num_adc_nids; n++) {
981 cap = spec->private_capsrc_nids[n];
982 for (i = 0; i < imux->num_items; i++) {
983 pin = spec->imux_pins[i];
984 if (!pin)
985 return false;
986 if (get_connection_index(codec, cap, pin) < 0)
987 break;
988 }
989 if (i >= imux->num_items)
Takashi Iwai268ff6f2011-07-08 14:37:35 +0200990 return true; /* no ADC-switch is needed */
Takashi Iwai1d045db2011-07-07 18:23:21 +0200991 }
992
993 for (i = 0; i < imux->num_items; i++) {
994 pin = spec->imux_pins[i];
995 for (n = 0; n < spec->num_adc_nids; n++) {
996 cap = spec->private_capsrc_nids[n];
997 idx = get_connection_index(codec, cap, pin);
998 if (idx >= 0) {
999 imux->items[i].index = idx;
1000 spec->dyn_adc_idx[i] = n;
1001 break;
1002 }
1003 }
1004 }
1005
1006 snd_printdd("realtek: enabling ADC switching\n");
1007 spec->dyn_adc_switch = 1;
1008 return true;
1009}
Takashi Iwai21268962011-07-07 15:01:13 +02001010
1011/* rebuild imux for matching with the given auto-mic pins (if not yet) */
1012static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
1013{
1014 struct alc_spec *spec = codec->spec;
1015 struct hda_input_mux *imux;
1016 static char * const texts[3] = {
1017 "Mic", "Internal Mic", "Dock Mic"
1018 };
1019 int i;
1020
1021 if (!spec->auto_mic)
1022 return false;
1023 imux = &spec->private_imux[0];
1024 if (spec->input_mux == imux)
1025 return true;
1026 spec->imux_pins[0] = spec->ext_mic_pin;
1027 spec->imux_pins[1] = spec->int_mic_pin;
1028 spec->imux_pins[2] = spec->dock_mic_pin;
1029 for (i = 0; i < 3; i++) {
1030 strcpy(imux->items[i].label, texts[i]);
1031 if (spec->imux_pins[i])
1032 imux->num_items = i + 1;
1033 }
1034 spec->num_mux_defs = 1;
1035 spec->input_mux = imux;
1036 return true;
1037}
1038
1039/* check whether all auto-mic pins are valid; setup indices if OK */
1040static bool alc_auto_mic_check_imux(struct hda_codec *codec)
1041{
1042 struct alc_spec *spec = codec->spec;
1043 const struct hda_input_mux *imux;
1044
1045 if (!spec->auto_mic)
1046 return false;
1047 if (spec->auto_mic_valid_imux)
1048 return true; /* already checked */
1049
1050 /* fill up imux indices */
1051 if (!alc_check_dyn_adc_switch(codec)) {
1052 spec->auto_mic = 0;
1053 return false;
1054 }
1055
1056 imux = spec->input_mux;
1057 spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
1058 spec->imux_pins, imux->num_items);
1059 spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
1060 spec->imux_pins, imux->num_items);
1061 spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
1062 spec->imux_pins, imux->num_items);
1063 if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
1064 spec->auto_mic = 0;
1065 return false; /* no corresponding imux */
1066 }
1067
1068 snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
1069 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001070 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001071 if (spec->dock_mic_pin)
1072 snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
1073 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001074 AC_USRSP_EN | ALC_MIC_EVENT);
Takashi Iwai21268962011-07-07 15:01:13 +02001075
1076 spec->auto_mic_valid_imux = 1;
1077 spec->auto_mic = 1;
1078 return true;
1079}
1080
Takashi Iwai1d045db2011-07-07 18:23:21 +02001081/*
1082 * Check the availability of auto-mic switch;
1083 * Set up if really supported
1084 */
Takashi Iwai6c819492009-08-10 18:47:44 +02001085static void alc_init_auto_mic(struct hda_codec *codec)
1086{
1087 struct alc_spec *spec = codec->spec;
1088 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001089 hda_nid_t fixed, ext, dock;
Takashi Iwai6c819492009-08-10 18:47:44 +02001090 int i;
1091
Takashi Iwai21268962011-07-07 15:01:13 +02001092 spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
1093
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001094 fixed = ext = dock = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001095 for (i = 0; i < cfg->num_inputs; i++) {
1096 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001097 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001098 defcfg = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001099 switch (snd_hda_get_input_pin_attr(defcfg)) {
1100 case INPUT_PIN_ATTR_INT:
Takashi Iwai6c819492009-08-10 18:47:44 +02001101 if (fixed)
1102 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001103 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1104 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001105 fixed = nid;
1106 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001107 case INPUT_PIN_ATTR_UNUSED:
1108 return; /* invalid entry */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001109 case INPUT_PIN_ATTR_DOCK:
1110 if (dock)
1111 return; /* already occupied */
1112 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1113 return; /* invalid type */
1114 dock = nid;
1115 break;
Takashi Iwai99ae28b2010-09-17 14:42:34 +02001116 default:
Takashi Iwai6c819492009-08-10 18:47:44 +02001117 if (ext)
1118 return; /* already occupied */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001119 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1120 return; /* invalid type */
Takashi Iwai6c819492009-08-10 18:47:44 +02001121 ext = nid;
1122 break;
Takashi Iwai6c819492009-08-10 18:47:44 +02001123 }
1124 }
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001125 if (!ext && dock) {
1126 ext = dock;
1127 dock = 0;
1128 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001129 if (!ext || !fixed)
1130 return;
Takashi Iwaie35d9d62011-05-17 11:28:16 +02001131 if (!is_jack_detectable(codec, ext))
Takashi Iwai6c819492009-08-10 18:47:44 +02001132 return; /* no unsol support */
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001133 if (dock && !is_jack_detectable(codec, dock))
1134 return; /* no unsol support */
Takashi Iwai21268962011-07-07 15:01:13 +02001135
1136 /* check imux indices */
1137 spec->ext_mic_pin = ext;
1138 spec->int_mic_pin = fixed;
1139 spec->dock_mic_pin = dock;
1140
1141 spec->auto_mic = 1;
1142 if (!alc_auto_mic_check_imux(codec))
1143 return;
1144
Takashi Iwai8ed99d92011-05-17 12:05:02 +02001145 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1146 ext, fixed, dock);
Takashi Iwai6c819492009-08-10 18:47:44 +02001147 spec->unsol_event = alc_sku_unsol_event;
1148}
1149
Takashi Iwai1d045db2011-07-07 18:23:21 +02001150/* check the availabilities of auto-mute and auto-mic switches */
1151static void alc_auto_check_switches(struct hda_codec *codec)
1152{
1153 alc_init_auto_hp(codec);
1154 alc_init_auto_mic(codec);
1155}
1156
1157/*
1158 * Realtek SSID verification
1159 */
1160
David Henningsson90622912010-10-14 14:50:18 +02001161/* Could be any non-zero and even value. When used as fixup, tells
1162 * the driver to ignore any present sku defines.
1163 */
1164#define ALC_FIXUP_SKU_IGNORE (2)
1165
Kailang Yangda00c242010-03-19 11:23:45 +01001166static int alc_auto_parse_customize_define(struct hda_codec *codec)
1167{
1168 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001169 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001170 struct alc_spec *spec = codec->spec;
1171
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001172 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1173
David Henningsson90622912010-10-14 14:50:18 +02001174 if (spec->cdefine.fixup) {
1175 ass = spec->cdefine.sku_cfg;
1176 if (ass == ALC_FIXUP_SKU_IGNORE)
1177 return -1;
1178 goto do_sku;
1179 }
1180
Kailang Yangda00c242010-03-19 11:23:45 +01001181 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001182 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001183 goto do_sku;
1184
1185 nid = 0x1d;
1186 if (codec->vendor_id == 0x10ec0260)
1187 nid = 0x17;
1188 ass = snd_hda_codec_get_pincfg(codec, nid);
1189
1190 if (!(ass & 1)) {
1191 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1192 codec->chip_name, ass);
1193 return -1;
1194 }
1195
1196 /* check sum */
1197 tmp = 0;
1198 for (i = 1; i < 16; i++) {
1199 if ((ass >> i) & 1)
1200 tmp++;
1201 }
1202 if (((ass >> 16) & 0xf) != tmp)
1203 return -1;
1204
1205 spec->cdefine.port_connectivity = ass >> 30;
1206 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1207 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1208 spec->cdefine.customization = ass >> 8;
1209do_sku:
1210 spec->cdefine.sku_cfg = ass;
1211 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1212 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1213 spec->cdefine.swap = (ass & 0x2) >> 1;
1214 spec->cdefine.override = ass & 0x1;
1215
1216 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1217 nid, spec->cdefine.sku_cfg);
1218 snd_printd("SKU: port_connectivity=0x%x\n",
1219 spec->cdefine.port_connectivity);
1220 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1221 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1222 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1223 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1224 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1225 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1226 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1227
1228 return 0;
1229}
1230
Takashi Iwai1d045db2011-07-07 18:23:21 +02001231/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001232static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1233{
Takashi Iwai21268962011-07-07 15:01:13 +02001234 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001235}
1236
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001237/* check subsystem ID and set up device-specific initialization;
1238 * return 1 if initialized, 0 if invalid SSID
1239 */
1240/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1241 * 31 ~ 16 : Manufacture ID
1242 * 15 ~ 8 : SKU ID
1243 * 7 ~ 0 : Assembly ID
1244 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1245 */
1246static int alc_subsystem_id(struct hda_codec *codec,
1247 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001248 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001249{
1250 unsigned int ass, tmp, i;
1251 unsigned nid;
1252 struct alc_spec *spec = codec->spec;
1253
David Henningsson90622912010-10-14 14:50:18 +02001254 if (spec->cdefine.fixup) {
1255 ass = spec->cdefine.sku_cfg;
1256 if (ass == ALC_FIXUP_SKU_IGNORE)
1257 return 0;
1258 goto do_sku;
1259 }
1260
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001261 ass = codec->subsystem_id & 0xffff;
1262 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1263 goto do_sku;
1264
1265 /* invalid SSID, check the special NID pin defcfg instead */
1266 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001267 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001268 * 29~21 : reserve
1269 * 20 : PCBEEP input
1270 * 19~16 : Check sum (15:1)
1271 * 15~1 : Custom
1272 * 0 : override
1273 */
1274 nid = 0x1d;
1275 if (codec->vendor_id == 0x10ec0260)
1276 nid = 0x17;
1277 ass = snd_hda_codec_get_pincfg(codec, nid);
1278 snd_printd("realtek: No valid SSID, "
1279 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001280 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001281 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001282 return 0;
1283 if ((ass >> 30) != 1) /* no physical connection */
1284 return 0;
1285
1286 /* check sum */
1287 tmp = 0;
1288 for (i = 1; i < 16; i++) {
1289 if ((ass >> i) & 1)
1290 tmp++;
1291 }
1292 if (((ass >> 16) & 0xf) != tmp)
1293 return 0;
1294do_sku:
1295 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1296 ass & 0xffff, codec->vendor_id);
1297 /*
1298 * 0 : override
1299 * 1 : Swap Jack
1300 * 2 : 0 --> Desktop, 1 --> Laptop
1301 * 3~5 : External Amplifier control
1302 * 7~6 : Reserved
1303 */
1304 tmp = (ass & 0x38) >> 3; /* external Amp control */
1305 switch (tmp) {
1306 case 1:
1307 spec->init_amp = ALC_INIT_GPIO1;
1308 break;
1309 case 3:
1310 spec->init_amp = ALC_INIT_GPIO2;
1311 break;
1312 case 7:
1313 spec->init_amp = ALC_INIT_GPIO3;
1314 break;
1315 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +01001316 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001317 spec->init_amp = ALC_INIT_DEFAULT;
1318 break;
1319 }
1320
1321 /* is laptop or Desktop and enable the function "Mute internal speaker
1322 * when the external headphone out jack is plugged"
1323 */
1324 if (!(ass & 0x8000))
1325 return 1;
1326 /*
1327 * 10~8 : Jack location
1328 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1329 * 14~13: Resvered
1330 * 15 : 1 --> enable the function "Mute internal speaker
1331 * when the external headphone out jack is plugged"
1332 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001333 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001334 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001335 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1336 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001337 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001338 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001339 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001340 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001341 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001342 else if (tmp == 3)
1343 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001344 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001345 return 1;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02001346 if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
1347 spec->autocfg.line_outs))
1348 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001349 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001350 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001351 return 1;
1352}
Kailang Yangea1fb292008-08-26 12:58:38 +02001353
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001354/* Check the validity of ALC subsystem-id
1355 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
1356static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001357{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001358 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001359 struct alc_spec *spec = codec->spec;
1360 snd_printd("realtek: "
1361 "Enable default setup for auto mode as fallback\n");
1362 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001363 }
Takashi Iwai21268962011-07-07 15:01:13 +02001364}
Takashi Iwai1a1455d2011-04-28 17:36:18 +02001365
Takashi Iwai41e41f12005-06-08 14:48:49 +02001366/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001367 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001368 */
1369
1370struct alc_pincfg {
1371 hda_nid_t nid;
1372 u32 val;
1373};
1374
Todd Broche1eb5f12010-12-06 11:19:51 -08001375struct alc_model_fixup {
1376 const int id;
1377 const char *name;
1378};
1379
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001380struct alc_fixup {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001381 int type;
Takashi Iwai361fe6e2011-01-14 09:55:32 +01001382 bool chained;
1383 int chain_id;
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001384 union {
1385 unsigned int sku;
1386 const struct alc_pincfg *pins;
1387 const struct hda_verb *verbs;
1388 void (*func)(struct hda_codec *codec,
1389 const struct alc_fixup *fix,
1390 int action);
1391 } v;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001392};
1393
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001394enum {
1395 ALC_FIXUP_INVALID,
1396 ALC_FIXUP_SKU,
1397 ALC_FIXUP_PINS,
1398 ALC_FIXUP_VERBS,
1399 ALC_FIXUP_FUNC,
1400};
Takashi Iwaif95474e2007-07-10 00:47:43 +02001401
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001402enum {
1403 ALC_FIXUP_ACT_PRE_PROBE,
1404 ALC_FIXUP_ACT_PROBE,
Takashi Iwai58701122011-01-13 15:41:45 +01001405 ALC_FIXUP_ACT_INIT,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001406};
1407
1408static void alc_apply_fixup(struct hda_codec *codec, int action)
1409{
1410 struct alc_spec *spec = codec->spec;
1411 int id = spec->fixup_id;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001412#ifdef CONFIG_SND_DEBUG_VERBOSE
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001413 const char *modelname = spec->fixup_name;
Takashi Iwaiaa1d0c52011-01-19 17:27:58 +01001414#endif
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001415 int depth = 0;
1416
1417 if (!spec->fixup_list)
1418 return;
1419
1420 while (id >= 0) {
1421 const struct alc_fixup *fix = spec->fixup_list + id;
1422 const struct alc_pincfg *cfg;
1423
1424 switch (fix->type) {
1425 case ALC_FIXUP_SKU:
1426 if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
1427 break;;
1428 snd_printdd(KERN_INFO "hda_codec: %s: "
1429 "Apply sku override for %s\n",
1430 codec->chip_name, modelname);
1431 spec->cdefine.sku_cfg = fix->v.sku;
1432 spec->cdefine.fixup = 1;
1433 break;
1434 case ALC_FIXUP_PINS:
1435 cfg = fix->v.pins;
1436 if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
1437 break;
1438 snd_printdd(KERN_INFO "hda_codec: %s: "
1439 "Apply pincfg for %s\n",
1440 codec->chip_name, modelname);
1441 for (; cfg->nid; cfg++)
1442 snd_hda_codec_set_pincfg(codec, cfg->nid,
1443 cfg->val);
1444 break;
1445 case ALC_FIXUP_VERBS:
1446 if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
1447 break;
1448 snd_printdd(KERN_INFO "hda_codec: %s: "
1449 "Apply fix-verbs for %s\n",
1450 codec->chip_name, modelname);
1451 add_verb(codec->spec, fix->v.verbs);
1452 break;
1453 case ALC_FIXUP_FUNC:
1454 if (!fix->v.func)
1455 break;
1456 snd_printdd(KERN_INFO "hda_codec: %s: "
1457 "Apply fix-func for %s\n",
1458 codec->chip_name, modelname);
1459 fix->v.func(codec, fix, action);
1460 break;
1461 default:
1462 snd_printk(KERN_ERR "hda_codec: %s: "
1463 "Invalid fixup type %d\n",
1464 codec->chip_name, fix->type);
1465 break;
1466 }
Takashi Iwai24af2b12011-05-02 13:55:36 +02001467 if (!fix->chained)
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001468 break;
1469 if (++depth > 10)
1470 break;
Takashi Iwai24af2b12011-05-02 13:55:36 +02001471 id = fix->chain_id;
Takashi Iwai9d578832010-11-22 13:29:19 +01001472 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001473}
1474
Todd Broche1eb5f12010-12-06 11:19:51 -08001475static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001476 const struct alc_model_fixup *models,
1477 const struct snd_pci_quirk *quirk,
1478 const struct alc_fixup *fixlist)
Todd Broche1eb5f12010-12-06 11:19:51 -08001479{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001480 struct alc_spec *spec = codec->spec;
1481 int id = -1;
1482 const char *name = NULL;
Todd Broche1eb5f12010-12-06 11:19:51 -08001483
Todd Broche1eb5f12010-12-06 11:19:51 -08001484 if (codec->modelname && models) {
1485 while (models->name) {
1486 if (!strcmp(codec->modelname, models->name)) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001487 id = models->id;
1488 name = models->name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001489 break;
1490 }
1491 models++;
1492 }
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01001493 }
1494 if (id < 0) {
1495 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1496 if (quirk) {
1497 id = quirk->value;
1498#ifdef CONFIG_SND_DEBUG_VERBOSE
1499 name = quirk->name;
1500#endif
1501 }
1502 }
1503
1504 spec->fixup_id = id;
1505 if (id >= 0) {
1506 spec->fixup_list = fixlist;
1507 spec->fixup_name = name;
Todd Broche1eb5f12010-12-06 11:19:51 -08001508 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001509}
1510
Takashi Iwai1d045db2011-07-07 18:23:21 +02001511/*
1512 * COEF access helper functions
1513 */
Kailang Yang274693f2009-12-03 10:07:50 +01001514static int alc_read_coef_idx(struct hda_codec *codec,
1515 unsigned int coef_idx)
1516{
1517 unsigned int val;
1518 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1519 coef_idx);
1520 val = snd_hda_codec_read(codec, 0x20, 0,
1521 AC_VERB_GET_PROC_COEF, 0);
1522 return val;
1523}
1524
Kailang Yang977ddd62010-09-15 10:02:29 +02001525static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1526 unsigned int coef_val)
1527{
1528 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1529 coef_idx);
1530 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1531 coef_val);
1532}
1533
Takashi Iwai1d045db2011-07-07 18:23:21 +02001534/*
1535 * Digital I/O handling
1536 */
1537
Takashi Iwai757899a2010-07-30 10:48:14 +02001538/* set right pin controls for digital I/O */
1539static void alc_auto_init_digital(struct hda_codec *codec)
1540{
1541 struct alc_spec *spec = codec->spec;
1542 int i;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001543 hda_nid_t pin, dac;
Takashi Iwai757899a2010-07-30 10:48:14 +02001544
1545 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1546 pin = spec->autocfg.dig_out_pins[i];
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02001547 if (!pin)
1548 continue;
1549 snd_hda_codec_write(codec, pin, 0,
1550 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1551 if (!i)
1552 dac = spec->multiout.dig_out_nid;
1553 else
1554 dac = spec->slave_dig_outs[i - 1];
1555 if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
1556 continue;
1557 snd_hda_codec_write(codec, dac, 0,
1558 AC_VERB_SET_AMP_GAIN_MUTE,
1559 AMP_OUT_UNMUTE);
Takashi Iwai757899a2010-07-30 10:48:14 +02001560 }
1561 pin = spec->autocfg.dig_in_pin;
1562 if (pin)
1563 snd_hda_codec_write(codec, pin, 0,
1564 AC_VERB_SET_PIN_WIDGET_CONTROL,
1565 PIN_IN);
1566}
1567
1568/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1569static void alc_auto_parse_digital(struct hda_codec *codec)
1570{
1571 struct alc_spec *spec = codec->spec;
1572 int i, err;
1573 hda_nid_t dig_nid;
1574
1575 /* support multiple SPDIFs; the secondary is set up as a slave */
1576 for (i = 0; i < spec->autocfg.dig_outs; i++) {
Takashi Iwaia9267572011-07-07 15:12:55 +02001577 hda_nid_t conn[4];
Takashi Iwai757899a2010-07-30 10:48:14 +02001578 err = snd_hda_get_connections(codec,
1579 spec->autocfg.dig_out_pins[i],
Takashi Iwaia9267572011-07-07 15:12:55 +02001580 conn, ARRAY_SIZE(conn));
Takashi Iwai757899a2010-07-30 10:48:14 +02001581 if (err < 0)
1582 continue;
Takashi Iwaia9267572011-07-07 15:12:55 +02001583 dig_nid = conn[0]; /* assume the first element is audio-out */
Takashi Iwai757899a2010-07-30 10:48:14 +02001584 if (!i) {
1585 spec->multiout.dig_out_nid = dig_nid;
1586 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1587 } else {
1588 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1589 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1590 break;
1591 spec->slave_dig_outs[i - 1] = dig_nid;
1592 }
1593 }
1594
1595 if (spec->autocfg.dig_in_pin) {
Takashi Iwai01fdf182010-09-24 09:09:42 +02001596 dig_nid = codec->start_nid;
1597 for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
1598 unsigned int wcaps = get_wcaps(codec, dig_nid);
1599 if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
1600 continue;
1601 if (!(wcaps & AC_WCAP_DIGITAL))
1602 continue;
1603 if (!(wcaps & AC_WCAP_CONN_LIST))
1604 continue;
1605 err = get_connection_index(codec, dig_nid,
1606 spec->autocfg.dig_in_pin);
1607 if (err >= 0) {
1608 spec->dig_in_nid = dig_nid;
1609 break;
1610 }
1611 }
Takashi Iwai757899a2010-07-30 10:48:14 +02001612 }
1613}
1614
Takashi Iwaif95474e2007-07-10 00:47:43 +02001615/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001616 * capture mixer elements
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001617 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001618static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1619 struct snd_ctl_elem_info *uinfo)
1620{
1621 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1622 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001623 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001624 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001625
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001626 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001627 if (spec->vol_in_capsrc)
1628 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1629 else
1630 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1631 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001632 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001633 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001634 return err;
1635}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001637static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1638 unsigned int size, unsigned int __user *tlv)
1639{
1640 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1641 struct alc_spec *spec = codec->spec;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001642 unsigned long val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001643 int err;
1644
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001645 mutex_lock(&codec->control_mutex);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001646 if (spec->vol_in_capsrc)
1647 val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
1648 else
1649 val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
1650 kcontrol->private_value = val;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001651 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001652 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001653 return err;
1654}
1655
1656typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1657 struct snd_ctl_elem_value *ucontrol);
1658
1659static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1660 struct snd_ctl_elem_value *ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001661 getput_call_t func, bool check_adc_switch)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001662{
1663 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1664 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02001665 int i, err = 0;
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001666
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001667 mutex_lock(&codec->control_mutex);
Takashi Iwai21268962011-07-07 15:01:13 +02001668 if (check_adc_switch && spec->dyn_adc_switch) {
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001669 for (i = 0; i < spec->num_adc_nids; i++) {
1670 kcontrol->private_value =
1671 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1672 3, 0, HDA_INPUT);
1673 err = func(kcontrol, ucontrol);
1674 if (err < 0)
1675 goto error;
1676 }
1677 } else {
1678 i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02001679 if (spec->vol_in_capsrc)
1680 kcontrol->private_value =
1681 HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
1682 3, 0, HDA_OUTPUT);
1683 else
1684 kcontrol->private_value =
Takashi Iwai21268962011-07-07 15:01:13 +02001685 HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
1686 3, 0, HDA_INPUT);
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001687 err = func(kcontrol, ucontrol);
1688 }
1689 error:
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001690 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001691 return err;
1692}
1693
1694static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1695 struct snd_ctl_elem_value *ucontrol)
1696{
1697 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001698 snd_hda_mixer_amp_volume_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001699}
1700
1701static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1702 struct snd_ctl_elem_value *ucontrol)
1703{
1704 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001705 snd_hda_mixer_amp_volume_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001706}
1707
1708/* capture mixer elements */
1709#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1710
1711static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
1712 struct snd_ctl_elem_value *ucontrol)
1713{
1714 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001715 snd_hda_mixer_amp_switch_get, false);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001716}
1717
1718static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
1719 struct snd_ctl_elem_value *ucontrol)
1720{
1721 return alc_cap_getput_caller(kcontrol, ucontrol,
Takashi Iwai9c7a0832011-07-07 09:25:54 +02001722 snd_hda_mixer_amp_switch_put, true);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001723}
1724
Takashi Iwaia23b6882009-03-23 15:21:36 +01001725#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001726 { \
1727 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1728 .name = "Capture Switch", \
1729 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1730 .count = num, \
1731 .info = alc_cap_sw_info, \
1732 .get = alc_cap_sw_get, \
1733 .put = alc_cap_sw_put, \
1734 }, \
1735 { \
1736 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1737 .name = "Capture Volume", \
1738 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1739 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1740 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
1741 .count = num, \
1742 .info = alc_cap_vol_info, \
1743 .get = alc_cap_vol_get, \
1744 .put = alc_cap_vol_put, \
1745 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001746 }
1747
1748#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01001749 { \
1750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1751 /* .name = "Capture Source", */ \
1752 .name = "Input Source", \
1753 .count = num, \
1754 .info = alc_mux_enum_info, \
1755 .get = alc_mux_enum_get, \
1756 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001757 }
1758
1759#define DEFINE_CAPMIX(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001760static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001761 _DEFINE_CAPMIX(num), \
1762 _DEFINE_CAPSRC(num), \
1763 { } /* end */ \
1764}
1765
1766#define DEFINE_CAPMIX_NOSRC(num) \
Takashi Iwaia9111322011-05-02 11:30:18 +02001767static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
Takashi Iwaia23b6882009-03-23 15:21:36 +01001768 _DEFINE_CAPMIX(num), \
1769 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001770}
1771
1772/* up to three ADCs */
1773DEFINE_CAPMIX(1);
1774DEFINE_CAPMIX(2);
1775DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01001776DEFINE_CAPMIX_NOSRC(1);
1777DEFINE_CAPMIX_NOSRC(2);
1778DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001779
1780/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01001781 * virtual master controls
1782 */
1783
1784/*
1785 * slave controls for virtual master
1786 */
Takashi Iwaiea734962011-01-17 11:29:34 +01001787static const char * const alc_slave_vols[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001788 "Front Playback Volume",
1789 "Surround Playback Volume",
1790 "Center Playback Volume",
1791 "LFE Playback Volume",
1792 "Side Playback Volume",
1793 "Headphone Playback Volume",
1794 "Speaker Playback Volume",
1795 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001796 "Line-Out Playback Volume",
1797 NULL,
1798};
1799
Takashi Iwaiea734962011-01-17 11:29:34 +01001800static const char * const alc_slave_sws[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001801 "Front Playback Switch",
1802 "Surround Playback Switch",
1803 "Center Playback Switch",
1804 "LFE Playback Switch",
1805 "Side Playback Switch",
1806 "Headphone Playback Switch",
1807 "Speaker Playback Switch",
1808 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01001809 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01001810 "Line-Out Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01001811 NULL,
1812};
1813
1814/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001815 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 */
Takashi Iwai603c4012008-07-30 15:01:44 +02001817
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001818#define NID_MAPPING (-1)
1819
1820#define SUBDEV_SPEAKER_ (0 << 6)
1821#define SUBDEV_HP_ (1 << 6)
1822#define SUBDEV_LINE_ (2 << 6)
1823#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
1824#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
1825#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
1826
Takashi Iwai603c4012008-07-30 15:01:44 +02001827static void alc_free_kctls(struct hda_codec *codec);
1828
Takashi Iwai67d634c2009-11-16 15:35:59 +01001829#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001830/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +02001831static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001832 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02001833 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001834 { } /* end */
1835};
Takashi Iwai67d634c2009-11-16 15:35:59 +01001836#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001837
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838static int alc_build_controls(struct hda_codec *codec)
1839{
1840 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02001841 struct snd_kcontrol *kctl = NULL;
Takashi Iwaia9111322011-05-02 11:30:18 +02001842 const struct snd_kcontrol_new *knew;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001843 int i, j, err;
1844 unsigned int u;
1845 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846
1847 for (i = 0; i < spec->num_mixers; i++) {
1848 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
1849 if (err < 0)
1850 return err;
1851 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001852 if (spec->cap_mixer) {
1853 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
1854 if (err < 0)
1855 return err;
1856 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001858 err = snd_hda_create_spdif_out_ctls(codec,
Stephen Warren74b654c2011-06-01 11:14:18 -06001859 spec->multiout.dig_out_nid,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001860 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 if (err < 0)
1862 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001863 if (!spec->no_analog) {
1864 err = snd_hda_create_spdif_share_sw(codec,
1865 &spec->multiout);
1866 if (err < 0)
1867 return err;
1868 spec->multiout.share_spdif = 1;
1869 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 }
1871 if (spec->dig_in_nid) {
1872 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
1873 if (err < 0)
1874 return err;
1875 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01001876
Takashi Iwai67d634c2009-11-16 15:35:59 +01001877#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001878 /* create beep controls if needed */
1879 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +02001880 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001881 for (knew = alc_beep_mixer; knew->name; knew++) {
1882 struct snd_kcontrol *kctl;
1883 kctl = snd_ctl_new1(knew, codec);
1884 if (!kctl)
1885 return -ENOMEM;
1886 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01001887 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001888 if (err < 0)
1889 return err;
1890 }
1891 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01001892#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01001893
Takashi Iwai2134ea42008-01-10 16:53:55 +01001894 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001895 if (!spec->no_analog &&
1896 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001897 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01001898 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001899 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001900 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01001901 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01001902 if (err < 0)
1903 return err;
1904 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01001905 if (!spec->no_analog &&
1906 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01001907 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
1908 NULL, alc_slave_sws);
1909 if (err < 0)
1910 return err;
1911 }
1912
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001913 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001914 if (spec->capsrc_nids || spec->adc_nids) {
1915 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
1916 if (!kctl)
1917 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
1918 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02001919 const hda_nid_t *nids = spec->capsrc_nids;
Takashi Iwaifbe618f2010-06-11 11:24:58 +02001920 if (!nids)
1921 nids = spec->adc_nids;
1922 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
1923 if (err < 0)
1924 return err;
1925 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001926 }
Takashi Iwai60a6a842011-07-27 14:01:24 +02001927 if (spec->cap_mixer && spec->adc_nids) {
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01001928 const char *kname = kctl ? kctl->id.name : NULL;
1929 for (knew = spec->cap_mixer; knew->name; knew++) {
1930 if (kname && strcmp(knew->name, kname) == 0)
1931 continue;
1932 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1933 for (i = 0; kctl && i < kctl->count; i++) {
1934 err = snd_hda_add_nid(codec, kctl, i,
1935 spec->adc_nids[i]);
1936 if (err < 0)
1937 return err;
1938 }
1939 }
1940 }
1941
1942 /* other nid->control mapping */
1943 for (i = 0; i < spec->num_mixers; i++) {
1944 for (knew = spec->mixers[i]; knew->name; knew++) {
1945 if (knew->iface != NID_MAPPING)
1946 continue;
1947 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
1948 if (kctl == NULL)
1949 continue;
1950 u = knew->subdevice;
1951 for (j = 0; j < 4; j++, u >>= 8) {
1952 nid = u & 0x3f;
1953 if (nid == 0)
1954 continue;
1955 switch (u & 0xc0) {
1956 case SUBDEV_SPEAKER_:
1957 nid = spec->autocfg.speaker_pins[nid];
1958 break;
1959 case SUBDEV_LINE_:
1960 nid = spec->autocfg.line_out_pins[nid];
1961 break;
1962 case SUBDEV_HP_:
1963 nid = spec->autocfg.hp_pins[nid];
1964 break;
1965 default:
1966 continue;
1967 }
1968 err = snd_hda_add_nid(codec, kctl, 0, nid);
1969 if (err < 0)
1970 return err;
1971 }
1972 u = knew->private_value;
1973 for (j = 0; j < 4; j++, u >>= 8) {
1974 nid = u & 0xff;
1975 if (nid == 0)
1976 continue;
1977 err = snd_hda_add_nid(codec, kctl, 0, nid);
1978 if (err < 0)
1979 return err;
1980 }
1981 }
1982 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01001983
1984 alc_free_kctls(codec); /* no longer needed */
1985
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 return 0;
1987}
1988
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001989
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01001991 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001992 */
Takashi Iwai16ded522005-06-10 19:58:24 +02001993
Takashi Iwai584c0c42011-03-10 12:51:11 +01001994static void alc_init_special_input_src(struct hda_codec *codec);
1995
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996static int alc_init(struct hda_codec *codec)
1997{
1998 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001999 unsigned int i;
2000
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002001 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02002002 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02002003
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002004 for (i = 0; i < spec->num_init_verbs; i++)
2005 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwai584c0c42011-03-10 12:51:11 +01002006 alc_init_special_input_src(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002007
2008 if (spec->init_hook)
2009 spec->init_hook(codec);
2010
Takashi Iwai58701122011-01-13 15:41:45 +01002011 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2012
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002013 hda_call_check_power_status(codec, 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 return 0;
2015}
2016
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002017static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2018{
2019 struct alc_spec *spec = codec->spec;
2020
2021 if (spec->unsol_event)
2022 spec->unsol_event(codec, res);
2023}
2024
Takashi Iwaicb53c622007-08-10 17:21:45 +02002025#ifdef CONFIG_SND_HDA_POWER_SAVE
2026static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
2027{
2028 struct alc_spec *spec = codec->spec;
2029 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
2030}
2031#endif
2032
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033/*
2034 * Analog playback callbacks
2035 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002036static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002038 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039{
2040 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01002041 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2042 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002045static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 struct hda_codec *codec,
2047 unsigned int stream_tag,
2048 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002049 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050{
2051 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002052 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2053 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054}
2055
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002056static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002058 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059{
2060 struct alc_spec *spec = codec->spec;
2061 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2062}
2063
2064/*
2065 * Digital out
2066 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002067static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002069 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070{
2071 struct alc_spec *spec = codec->spec;
2072 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
2073}
2074
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002075static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02002076 struct hda_codec *codec,
2077 unsigned int stream_tag,
2078 unsigned int format,
2079 struct snd_pcm_substream *substream)
2080{
2081 struct alc_spec *spec = codec->spec;
2082 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
2083 stream_tag, format, substream);
2084}
2085
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002086static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01002087 struct hda_codec *codec,
2088 struct snd_pcm_substream *substream)
2089{
2090 struct alc_spec *spec = codec->spec;
2091 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
2092}
2093
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002094static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002096 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097{
2098 struct alc_spec *spec = codec->spec;
2099 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
2100}
2101
2102/*
2103 * Analog capture
2104 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002105static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 struct hda_codec *codec,
2107 unsigned int stream_tag,
2108 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002109 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110{
2111 struct alc_spec *spec = codec->spec;
2112
Takashi Iwai63300792008-01-24 15:31:36 +01002113 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 stream_tag, 0, format);
2115 return 0;
2116}
2117
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002118static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002120 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121{
2122 struct alc_spec *spec = codec->spec;
2123
Takashi Iwai888afa12008-03-18 09:57:50 +01002124 snd_hda_codec_cleanup_stream(codec,
2125 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 return 0;
2127}
2128
Takashi Iwai840b64c2010-07-13 22:49:01 +02002129/* analog capture with dynamic dual-adc changes */
Takashi Iwai21268962011-07-07 15:01:13 +02002130static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002131 struct hda_codec *codec,
2132 unsigned int stream_tag,
2133 unsigned int format,
2134 struct snd_pcm_substream *substream)
2135{
2136 struct alc_spec *spec = codec->spec;
Takashi Iwai21268962011-07-07 15:01:13 +02002137 spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
Takashi Iwai840b64c2010-07-13 22:49:01 +02002138 spec->cur_adc_stream_tag = stream_tag;
2139 spec->cur_adc_format = format;
2140 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
2141 return 0;
2142}
2143
Takashi Iwai21268962011-07-07 15:01:13 +02002144static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Takashi Iwai840b64c2010-07-13 22:49:01 +02002145 struct hda_codec *codec,
2146 struct snd_pcm_substream *substream)
2147{
2148 struct alc_spec *spec = codec->spec;
2149 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
2150 spec->cur_adc = 0;
2151 return 0;
2152}
2153
Takashi Iwai21268962011-07-07 15:01:13 +02002154static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
Takashi Iwai840b64c2010-07-13 22:49:01 +02002155 .substreams = 1,
2156 .channels_min = 2,
2157 .channels_max = 2,
2158 .nid = 0, /* fill later */
2159 .ops = {
Takashi Iwai21268962011-07-07 15:01:13 +02002160 .prepare = dyn_adc_capture_pcm_prepare,
2161 .cleanup = dyn_adc_capture_pcm_cleanup
Takashi Iwai840b64c2010-07-13 22:49:01 +02002162 },
2163};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164
2165/*
2166 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002167static const struct hda_pcm_stream alc_pcm_analog_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 .substreams = 1,
2169 .channels_min = 2,
2170 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002171 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002173 .open = alc_playback_pcm_open,
2174 .prepare = alc_playback_pcm_prepare,
2175 .cleanup = alc_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 },
2177};
2178
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002179static const struct hda_pcm_stream alc_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002180 .substreams = 1,
2181 .channels_min = 2,
2182 .channels_max = 2,
2183 /* NID is set in alc_build_pcms */
2184};
2185
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002186static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
Takashi Iwai63300792008-01-24 15:31:36 +01002187 .substreams = 1,
2188 .channels_min = 2,
2189 .channels_max = 2,
2190 /* NID is set in alc_build_pcms */
2191};
2192
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002193static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01002194 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 .channels_min = 2,
2196 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002197 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002199 .prepare = alc_alt_capture_pcm_prepare,
2200 .cleanup = alc_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 },
2202};
2203
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002204static const struct hda_pcm_stream alc_pcm_digital_playback = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 .substreams = 1,
2206 .channels_min = 2,
2207 .channels_max = 2,
2208 /* NID is set in alc_build_pcms */
2209 .ops = {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002210 .open = alc_dig_playback_pcm_open,
2211 .close = alc_dig_playback_pcm_close,
2212 .prepare = alc_dig_playback_pcm_prepare,
2213 .cleanup = alc_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 },
2215};
2216
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002217static const struct hda_pcm_stream alc_pcm_digital_capture = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 .substreams = 1,
2219 .channels_min = 2,
2220 .channels_max = 2,
2221 /* NID is set in alc_build_pcms */
2222};
2223
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002224/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwaia9111322011-05-02 11:30:18 +02002225static const struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01002226 .substreams = 0,
2227 .channels_min = 0,
2228 .channels_max = 0,
2229};
2230
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231static int alc_build_pcms(struct hda_codec *codec)
2232{
2233 struct alc_spec *spec = codec->spec;
2234 struct hda_pcm *info = spec->pcm_rec;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002235 const struct hda_pcm_stream *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 int i;
2237
2238 codec->num_pcms = 1;
2239 codec->pcm_info = info;
2240
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002241 if (spec->no_analog)
2242 goto skip_analog;
2243
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002244 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
2245 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01002247
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002248 if (spec->multiout.dac_nids > 0) {
2249 p = spec->stream_analog_playback;
2250 if (!p)
2251 p = &alc_pcm_analog_playback;
2252 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002253 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
2254 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002255 if (spec->adc_nids) {
2256 p = spec->stream_analog_capture;
Takashi Iwai21268962011-07-07 15:01:13 +02002257 if (!p) {
2258 if (spec->dyn_adc_switch)
2259 p = &dyn_adc_pcm_analog_capture;
2260 else
2261 p = &alc_pcm_analog_capture;
2262 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002263 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai4a471b72005-12-07 13:56:29 +01002264 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
2265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266
Takashi Iwai4a471b72005-12-07 13:56:29 +01002267 if (spec->channel_mode) {
2268 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
2269 for (i = 0; i < spec->num_channel_mode; i++) {
2270 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
2271 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
2272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 }
2274 }
2275
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002276 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02002277 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02002279 snprintf(spec->stream_name_digital,
2280 sizeof(spec->stream_name_digital),
2281 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02002282 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08002283 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002284 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01002286 if (spec->dig_out_type)
2287 info->pcm_type = spec->dig_out_type;
2288 else
2289 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002290 if (spec->multiout.dig_out_nid) {
2291 p = spec->stream_digital_playback;
2292 if (!p)
2293 p = &alc_pcm_digital_playback;
2294 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
2296 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002297 if (spec->dig_in_nid) {
2298 p = spec->stream_digital_capture;
2299 if (!p)
2300 p = &alc_pcm_digital_capture;
2301 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
2303 }
Takashi Iwai963f8032008-08-11 10:04:40 +02002304 /* FIXME: do we need this for all Realtek codec models? */
2305 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 }
2307
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002308 if (spec->no_analog)
2309 return 0;
2310
Takashi Iwaie08a0072006-09-07 17:52:14 +02002311 /* If the use of more than one ADC is requested for the current
2312 * model, configure a second analog capture-only PCM.
2313 */
2314 /* Additional Analaog capture for index #2 */
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002315 if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02002316 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02002317 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002318 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01002319 if (spec->alt_dac_nid) {
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002320 p = spec->stream_analog_alt_playback;
2321 if (!p)
2322 p = &alc_pcm_analog_alt_playback;
2323 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002324 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2325 spec->alt_dac_nid;
2326 } else {
2327 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2328 alc_pcm_null_stream;
2329 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2330 }
Takashi Iwaic2d986b2011-07-06 18:30:08 +02002331 if (spec->num_adc_nids > 1) {
2332 p = spec->stream_analog_alt_capture;
2333 if (!p)
2334 p = &alc_pcm_analog_alt_capture;
2335 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
Takashi Iwai63300792008-01-24 15:31:36 +01002336 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2337 spec->adc_nids[1];
2338 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2339 spec->num_adc_nids - 1;
2340 } else {
2341 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2342 alc_pcm_null_stream;
2343 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02002344 }
2345 }
2346
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 return 0;
2348}
2349
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002350static inline void alc_shutup(struct hda_codec *codec)
2351{
Takashi Iwai1c716152011-04-07 10:37:16 +02002352 struct alc_spec *spec = codec->spec;
2353
2354 if (spec && spec->shutup)
2355 spec->shutup(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002356 snd_hda_shutup_pins(codec);
2357}
2358
Takashi Iwai603c4012008-07-30 15:01:44 +02002359static void alc_free_kctls(struct hda_codec *codec)
2360{
2361 struct alc_spec *spec = codec->spec;
2362
2363 if (spec->kctls.list) {
2364 struct snd_kcontrol_new *kctl = spec->kctls.list;
2365 int i;
2366 for (i = 0; i < spec->kctls.used; i++)
2367 kfree(kctl[i].name);
2368 }
2369 snd_array_free(&spec->kctls);
2370}
2371
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372static void alc_free(struct hda_codec *codec)
2373{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002374 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002375
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002376 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002377 return;
2378
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002379 alc_shutup(codec);
Takashi Iwaicd372fb2011-03-03 14:40:14 +01002380 snd_hda_input_jack_free(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002381 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002382 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09002383 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384}
2385
Hector Martinf5de24b2009-12-20 22:51:31 +01002386#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05002387static void alc_power_eapd(struct hda_codec *codec)
2388{
Takashi Iwai691f1fc2011-04-07 10:31:43 +02002389 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -05002390}
2391
Hector Martinf5de24b2009-12-20 22:51:31 +01002392static int alc_suspend(struct hda_codec *codec, pm_message_t state)
2393{
2394 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01002395 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002396 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05002397 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01002398 return 0;
2399}
2400#endif
2401
Takashi Iwai2a439522011-07-26 09:52:50 +02002402#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002403static int alc_resume(struct hda_codec *codec)
2404{
Takashi Iwai1c716152011-04-07 10:37:16 +02002405 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +01002406 codec->patch_ops.init(codec);
2407 snd_hda_codec_resume_amp(codec);
2408 snd_hda_codec_resume_cache(codec);
Takashi Iwai9e5341b2010-09-21 09:57:06 +02002409 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +01002410 return 0;
2411}
Takashi Iwaie044c392008-10-27 16:56:24 +01002412#endif
2413
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414/*
2415 */
Takashi Iwaia9111322011-05-02 11:30:18 +02002416static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 .build_controls = alc_build_controls,
2418 .build_pcms = alc_build_pcms,
2419 .init = alc_init,
2420 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01002421 .unsol_event = alc_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +02002422#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +01002423 .resume = alc_resume,
2424#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02002425#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01002426 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02002427 .check_power_status = alc_check_power_status,
2428#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05002429 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430};
2431
Kailang Yangc027ddc2010-03-19 11:33:06 +01002432/* replace the codec chip_name with the given string */
2433static int alc_codec_rename(struct hda_codec *codec, const char *name)
2434{
2435 kfree(codec->chip_name);
2436 codec->chip_name = kstrdup(name, GFP_KERNEL);
2437 if (!codec->chip_name) {
2438 alc_free(codec);
2439 return -ENOMEM;
2440 }
2441 return 0;
2442}
2443
Takashi Iwai2fa522b2005-05-12 14:51:12 +02002444/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002445 * Automatic parse of I/O pins from the BIOS configuration
2446 */
2447
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002448enum {
2449 ALC_CTL_WIDGET_VOL,
2450 ALC_CTL_WIDGET_MUTE,
2451 ALC_CTL_BIND_MUTE,
2452};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002453static const struct snd_kcontrol_new alc_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002454 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2455 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01002456 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002457};
2458
2459/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002460static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002461 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002462{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002463 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002464
Takashi Iwaice764ab2011-04-27 16:35:23 +02002465 knew = alc_kcontrol_new(spec);
Takashi Iwai603c4012008-07-30 15:01:44 +02002466 if (!knew)
2467 return -ENOMEM;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002468 *knew = alc_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07002469 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002470 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002471 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002472 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01002473 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002474 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002475 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002476 return 0;
2477}
2478
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002479static int add_control_with_pfx(struct alc_spec *spec, int type,
2480 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002481 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002482{
2483 char name[32];
2484 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002485 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002486}
2487
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002488#define add_pb_vol_ctrl(spec, type, pfx, val) \
2489 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
2490#define add_pb_sw_ctrl(spec, type, pfx, val) \
2491 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
2492#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
2493 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
2494#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
2495 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02002496
Takashi Iwai6843ca12011-06-24 11:03:58 +02002497static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2498 bool can_be_master, int *index)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002499{
Takashi Iwaice764ab2011-04-27 16:35:23 +02002500 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai6843ca12011-06-24 11:03:58 +02002501 static const char * const chname[4] = {
2502 "Front", "Surround", NULL /*CLFE*/, "Side"
2503 };
Takashi Iwaice764ab2011-04-27 16:35:23 +02002504
Takashi Iwai6843ca12011-06-24 11:03:58 +02002505 *index = 0;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002506 if (cfg->line_outs == 1 && !spec->multi_ios &&
2507 !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002508 return "Master";
2509
2510 switch (cfg->line_out_type) {
2511 case AUTO_PIN_SPEAKER_OUT:
David Henningssonebbeb3d2011-03-04 14:08:30 +01002512 if (cfg->line_outs == 1)
2513 return "Speaker";
2514 break;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002515 case AUTO_PIN_HP_OUT:
Takashi Iwai6843ca12011-06-24 11:03:58 +02002516 /* for multi-io case, only the primary out */
2517 if (ch && spec->multi_ios)
2518 break;
2519 *index = ch;
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002520 return "Headphone";
2521 default:
Takashi Iwaice764ab2011-04-27 16:35:23 +02002522 if (cfg->line_outs == 1 && !spec->multi_ios)
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002523 return "PCM";
2524 break;
2525 }
Takashi Iwai6843ca12011-06-24 11:03:58 +02002526 return chname[ch];
Takashi Iwaibcb2f0f2011-01-10 15:45:23 +01002527}
2528
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002529/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002530static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002531 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01002532 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002533{
Kailang Yangdf694da2005-12-05 19:42:22 +01002534 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002535
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002536 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002537 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2538 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002539 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002540 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002541 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
2542 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002543 return err;
2544 return 0;
2545}
2546
Takashi Iwai05f5f472009-08-25 13:10:18 +02002547static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002548{
Takashi Iwai05f5f472009-08-25 13:10:18 +02002549 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2550 return (pincap & AC_PINCAP_IN) != 0;
2551}
2552
Takashi Iwai1d045db2011-07-07 18:23:21 +02002553/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002554static int alc_auto_fill_adc_caps(struct hda_codec *codec)
Takashi Iwaib7821702011-07-06 15:12:46 +02002555{
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002556 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002557 hda_nid_t nid;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002558 hda_nid_t *adc_nids = spec->private_adc_nids;
2559 hda_nid_t *cap_nids = spec->private_capsrc_nids;
2560 int max_nums = ARRAY_SIZE(spec->private_adc_nids);
2561 bool indep_capsrc = false;
Takashi Iwaib7821702011-07-06 15:12:46 +02002562 int i, nums = 0;
2563
2564 nid = codec->start_nid;
2565 for (i = 0; i < codec->num_nodes; i++, nid++) {
2566 hda_nid_t src;
2567 const hda_nid_t *list;
2568 unsigned int caps = get_wcaps(codec, nid);
2569 int type = get_wcaps_type(caps);
2570
2571 if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2572 continue;
2573 adc_nids[nums] = nid;
2574 cap_nids[nums] = nid;
2575 src = nid;
2576 for (;;) {
2577 int n;
2578 type = get_wcaps_type(get_wcaps(codec, src));
2579 if (type == AC_WID_PIN)
2580 break;
2581 if (type == AC_WID_AUD_SEL) {
2582 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002583 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002584 break;
2585 }
2586 n = snd_hda_get_conn_list(codec, src, &list);
2587 if (n > 1) {
2588 cap_nids[nums] = src;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002589 indep_capsrc = true;
Takashi Iwaib7821702011-07-06 15:12:46 +02002590 break;
2591 } else if (n != 1)
2592 break;
2593 src = *list;
2594 }
2595 if (++nums >= max_nums)
2596 break;
2597 }
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002598 spec->adc_nids = spec->private_adc_nids;
Takashi Iwai21268962011-07-07 15:01:13 +02002599 spec->capsrc_nids = spec->private_capsrc_nids;
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002600 spec->num_adc_nids = nums;
Takashi Iwaib7821702011-07-06 15:12:46 +02002601 return nums;
2602}
2603
Takashi Iwai05f5f472009-08-25 13:10:18 +02002604/* create playback/capture controls for input pins */
Takashi Iwaib7821702011-07-06 15:12:46 +02002605static int alc_auto_create_input_ctls(struct hda_codec *codec)
Takashi Iwai05f5f472009-08-25 13:10:18 +02002606{
2607 struct alc_spec *spec = codec->spec;
Takashi Iwaib7821702011-07-06 15:12:46 +02002608 const struct auto_pin_cfg *cfg = &spec->autocfg;
2609 hda_nid_t mixer = spec->mixer_nid;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02002610 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwaib7821702011-07-06 15:12:46 +02002611 int num_adcs;
Takashi Iwaib7821702011-07-06 15:12:46 +02002612 int i, c, err, idx, type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002613 const char *prev_label = NULL;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002614
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002615 num_adcs = alc_auto_fill_adc_caps(codec);
Takashi Iwaib7821702011-07-06 15:12:46 +02002616 if (num_adcs < 0)
2617 return 0;
2618
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002619 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02002620 hda_nid_t pin;
Takashi Iwai10a20af2010-09-09 16:28:02 +02002621 const char *label;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002622
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002623 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002624 if (!alc_is_input_pin(codec, pin))
2625 continue;
2626
David Henningsson5322bf22011-01-05 11:03:56 +01002627 label = hda_get_autocfg_input_label(codec, cfg, i);
2628 if (prev_label && !strcmp(label, prev_label))
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002629 type_idx++;
2630 else
2631 type_idx = 0;
David Henningsson5322bf22011-01-05 11:03:56 +01002632 prev_label = label;
2633
Takashi Iwai05f5f472009-08-25 13:10:18 +02002634 if (mixer) {
2635 idx = get_connection_index(codec, mixer, pin);
2636 if (idx >= 0) {
2637 err = new_analog_input(spec, pin,
Takashi Iwai10a20af2010-09-09 16:28:02 +02002638 label, type_idx,
2639 idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02002640 if (err < 0)
2641 return err;
2642 }
2643 }
2644
Takashi Iwaib7821702011-07-06 15:12:46 +02002645 for (c = 0; c < num_adcs; c++) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02002646 hda_nid_t cap = spec->capsrc_nids ?
2647 spec->capsrc_nids[c] : spec->adc_nids[c];
2648 idx = get_connection_index(codec, cap, pin);
Takashi Iwaib7821702011-07-06 15:12:46 +02002649 if (idx >= 0) {
Takashi Iwai21268962011-07-07 15:01:13 +02002650 spec->imux_pins[imux->num_items] = pin;
Takashi Iwaib7821702011-07-06 15:12:46 +02002651 snd_hda_add_imux_item(imux, label, idx, NULL);
2652 break;
2653 }
2654 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002655 }
Takashi Iwai21268962011-07-07 15:01:13 +02002656
2657 spec->num_mux_defs = 1;
2658 spec->input_mux = imux;
2659
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002660 return 0;
2661}
2662
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002663static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
2664 unsigned int pin_type)
2665{
2666 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2667 pin_type);
2668 /* unmute pin */
Takashi Iwai44c02402011-07-08 15:14:19 +02002669 if (nid_has_mute(codec, nid, HDA_OUTPUT))
2670 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaid260cdf2008-02-13 17:19:35 +01002671 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01002672}
2673
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02002674static int get_pin_type(int line_out_type)
2675{
2676 if (line_out_type == AUTO_PIN_HP_OUT)
2677 return PIN_HP;
2678 else
2679 return PIN_OUT;
2680}
2681
Takashi Iwai0a7f5322011-07-06 15:15:12 +02002682static void alc_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002683{
2684 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002685 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002686 int i;
2687
Takashi Iwai66ceeb62010-08-30 13:05:52 +02002688 for (i = 0; i < cfg->num_inputs; i++) {
2689 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02002690 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai30ea0982010-09-16 18:47:56 +02002691 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002692 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002693 snd_hda_codec_write(codec, nid, 0,
2694 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002695 AMP_OUT_MUTE);
2696 }
2697 }
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02002698
2699 /* mute all loopback inputs */
2700 if (spec->mixer_nid) {
2701 int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
2702 for (i = 0; i < nums; i++)
2703 snd_hda_codec_write(codec, spec->mixer_nid, 0,
2704 AC_VERB_SET_AMP_GAIN_MUTE,
2705 AMP_IN_MUTE(i));
2706 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002707}
2708
Takashi Iwai7085ec12009-10-02 09:03:58 +02002709/* convert from MIX nid to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002710static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002711{
Takashi Iwai604401a2011-04-27 15:14:23 +02002712 hda_nid_t list[5];
Takashi Iwai1304ac82011-04-06 15:16:21 +02002713 int i, num;
2714
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002715 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
2716 return nid;
Takashi Iwai1304ac82011-04-06 15:16:21 +02002717 num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
2718 for (i = 0; i < num; i++) {
2719 if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
2720 return list[i];
2721 }
2722 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002723}
2724
Takashi Iwai604401a2011-04-27 15:14:23 +02002725/* go down to the selector widget before the mixer */
2726static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
2727{
2728 hda_nid_t srcs[5];
2729 int num = snd_hda_get_connections(codec, pin, srcs,
2730 ARRAY_SIZE(srcs));
2731 if (num != 1 ||
2732 get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
2733 return pin;
2734 return srcs[0];
2735}
2736
Takashi Iwai7085ec12009-10-02 09:03:58 +02002737/* get MIX nid connected to the given pin targeted to DAC */
Takashi Iwai604401a2011-04-27 15:14:23 +02002738static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002739 hda_nid_t dac)
2740{
David Henningssoncc1c4522010-11-24 14:17:47 +01002741 hda_nid_t mix[5];
Takashi Iwai7085ec12009-10-02 09:03:58 +02002742 int i, num;
2743
Takashi Iwai604401a2011-04-27 15:14:23 +02002744 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002745 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2746 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002747 if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002748 return mix[i];
2749 }
2750 return 0;
2751}
2752
Takashi Iwaice764ab2011-04-27 16:35:23 +02002753/* select the connection from pin to DAC if needed */
2754static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
2755 hda_nid_t dac)
2756{
2757 hda_nid_t mix[5];
2758 int i, num;
2759
2760 pin = alc_go_down_to_selector(codec, pin);
2761 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
2762 if (num < 2)
2763 return 0;
2764 for (i = 0; i < num; i++) {
2765 if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
2766 snd_hda_codec_update_cache(codec, pin, 0,
2767 AC_VERB_SET_CONNECT_SEL, i);
2768 return 0;
2769 }
2770 }
2771 return 0;
2772}
2773
Takashi Iwai7085ec12009-10-02 09:03:58 +02002774/* look for an empty DAC slot */
Takashi Iwai604401a2011-04-27 15:14:23 +02002775static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002776{
2777 struct alc_spec *spec = codec->spec;
2778 hda_nid_t srcs[5];
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002779 int i, num;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002780
Takashi Iwai604401a2011-04-27 15:14:23 +02002781 pin = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002782 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002783 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02002784 hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002785 if (!nid)
2786 continue;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002787 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2788 spec->multiout.num_dacs))
2789 continue;
2790 if (spec->multiout.hp_nid == nid)
2791 continue;
2792 if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
2793 ARRAY_SIZE(spec->multiout.extra_out_nid)))
2794 continue;
2795 return nid;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002796 }
2797 return 0;
2798}
2799
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002800static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
2801{
2802 hda_nid_t sel = alc_go_down_to_selector(codec, pin);
2803 if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
2804 return alc_auto_look_for_dac(codec, pin);
2805 return 0;
2806}
2807
Takashi Iwai7085ec12009-10-02 09:03:58 +02002808/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002809static int alc_auto_fill_dac_nids(struct hda_codec *codec)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002810{
2811 struct alc_spec *spec = codec->spec;
Takashi Iwaicb053a82011-06-27 11:32:07 +02002812 const struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai350434e2011-06-30 21:29:12 +02002813 bool redone = false;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002814 int i;
Takashi Iwai7085ec12009-10-02 09:03:58 +02002815
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002816 again:
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002817 /* set num_dacs once to full for alc_auto_look_for_dac() */
2818 spec->multiout.num_dacs = cfg->line_outs;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002819 spec->multiout.hp_nid = 0;
2820 spec->multiout.extra_out_nid[0] = 0;
2821 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2822 spec->multiout.dac_nids = spec->private_dac_nids;
2823
2824 /* fill hard-wired DACs first */
2825 if (!redone) {
2826 for (i = 0; i < cfg->line_outs; i++)
2827 spec->private_dac_nids[i] =
2828 get_dac_if_single(codec, cfg->line_out_pins[i]);
2829 if (cfg->hp_outs)
2830 spec->multiout.hp_nid =
2831 get_dac_if_single(codec, cfg->hp_pins[0]);
2832 if (cfg->speaker_outs)
2833 spec->multiout.extra_out_nid[0] =
2834 get_dac_if_single(codec, cfg->speaker_pins[0]);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002835 }
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002836
2837 for (i = 0; i < cfg->line_outs; i++) {
2838 hda_nid_t pin = cfg->line_out_pins[i];
2839 if (spec->private_dac_nids[i])
2840 continue;
2841 spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
2842 if (!spec->private_dac_nids[i] && !redone) {
2843 /* if we can't find primary DACs, re-probe without
2844 * checking the hard-wired DACs
2845 */
2846 redone = true;
2847 goto again;
2848 }
2849 }
2850
Takashi Iwai8f398ae2011-07-23 18:57:11 +02002851 /* re-count num_dacs and squash invalid entries */
2852 spec->multiout.num_dacs = 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002853 for (i = 0; i < cfg->line_outs; i++) {
2854 if (spec->private_dac_nids[i])
2855 spec->multiout.num_dacs++;
2856 else
2857 memmove(spec->private_dac_nids + i,
2858 spec->private_dac_nids + i + 1,
2859 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
2860 }
2861
Takashi Iwaibb8bf4d2011-07-06 13:07:54 +02002862 if (cfg->hp_outs && !spec->multiout.hp_nid)
2863 spec->multiout.hp_nid =
2864 alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
2865 if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
2866 spec->multiout.extra_out_nid[0] =
2867 alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
2868
Takashi Iwai7085ec12009-10-02 09:03:58 +02002869 return 0;
2870}
2871
Takashi Iwai343a04b2011-07-06 14:28:39 +02002872static int alc_auto_add_vol_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002873 const char *pfx, int cidx,
2874 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002875{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002876 if (!nid)
2877 return 0;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002878 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
2879 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
Takashi Iwai7085ec12009-10-02 09:03:58 +02002880}
2881
Takashi Iwai343a04b2011-07-06 14:28:39 +02002882#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
2883 alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai97aaab72011-07-06 14:02:55 +02002884
2885/* create a mute-switch for the given mixer widget;
2886 * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
2887 */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002888static int alc_auto_add_sw_ctl(struct hda_codec *codec,
Takashi Iwai97aaab72011-07-06 14:02:55 +02002889 const char *pfx, int cidx,
2890 hda_nid_t nid, unsigned int chs)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002891{
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002892 int wid_type;
Takashi Iwai97aaab72011-07-06 14:02:55 +02002893 int type;
2894 unsigned long val;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002895 if (!nid)
2896 return 0;
2897 wid_type = get_wcaps_type(get_wcaps(codec, nid));
2898 if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
2899 type = ALC_CTL_WIDGET_MUTE;
2900 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
2901 } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
Takashi Iwai97aaab72011-07-06 14:02:55 +02002902 type = ALC_CTL_WIDGET_MUTE;
2903 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
2904 } else {
2905 type = ALC_CTL_BIND_MUTE;
2906 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
2907 }
2908 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
Takashi Iwai7085ec12009-10-02 09:03:58 +02002909}
2910
Takashi Iwai343a04b2011-07-06 14:28:39 +02002911#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
2912 alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
Takashi Iwai7085ec12009-10-02 09:03:58 +02002913
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002914static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
2915 hda_nid_t pin, hda_nid_t dac)
2916{
2917 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2918 if (nid_has_mute(codec, pin, HDA_OUTPUT))
2919 return pin;
2920 else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
2921 return mix;
2922 else if (nid_has_mute(codec, dac, HDA_OUTPUT))
2923 return dac;
2924 return 0;
2925}
2926
2927static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
2928 hda_nid_t pin, hda_nid_t dac)
2929{
2930 hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
2931 if (nid_has_volume(codec, dac, HDA_OUTPUT))
2932 return dac;
2933 else if (nid_has_volume(codec, mix, HDA_OUTPUT))
2934 return mix;
2935 else if (nid_has_volume(codec, pin, HDA_OUTPUT))
2936 return pin;
2937 return 0;
2938}
2939
Takashi Iwai7085ec12009-10-02 09:03:58 +02002940/* add playback controls from the parsed DAC table */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002941static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
Takashi Iwai7085ec12009-10-02 09:03:58 +02002942 const struct auto_pin_cfg *cfg)
2943{
2944 struct alc_spec *spec = codec->spec;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002945 int i, err, noutputs;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002946
Takashi Iwaice764ab2011-04-27 16:35:23 +02002947 noutputs = cfg->line_outs;
2948 if (spec->multi_ios > 0)
2949 noutputs += spec->multi_ios;
2950
2951 for (i = 0; i < noutputs; i++) {
Takashi Iwai6843ca12011-06-24 11:03:58 +02002952 const char *name;
2953 int index;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002954 hda_nid_t dac, pin;
2955 hda_nid_t sw, vol;
2956
2957 dac = spec->multiout.dac_nids[i];
2958 if (!dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002959 continue;
Takashi Iwaice764ab2011-04-27 16:35:23 +02002960 if (i >= cfg->line_outs)
2961 pin = spec->multi_io[i - 1].pin;
2962 else
2963 pin = cfg->line_out_pins[i];
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002964
2965 sw = alc_look_for_out_mute_nid(codec, pin, dac);
2966 vol = alc_look_for_out_vol_nid(codec, pin, dac);
Takashi Iwai6843ca12011-06-24 11:03:58 +02002967 name = alc_get_line_out_pfx(spec, i, true, &index);
2968 if (!name) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002969 /* Center/LFE */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002970 err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002971 if (err < 0)
2972 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002973 err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002974 if (err < 0)
2975 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002976 err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002977 if (err < 0)
2978 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002979 err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002980 if (err < 0)
2981 return err;
2982 } else {
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002983 err = alc_auto_add_stereo_vol(codec, name, index, vol);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002984 if (err < 0)
2985 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002986 err = alc_auto_add_stereo_sw(codec, name, index, sw);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002987 if (err < 0)
2988 return err;
2989 }
2990 }
2991 return 0;
2992}
2993
2994/* add playback controls for speaker and HP outputs */
Takashi Iwai343a04b2011-07-06 14:28:39 +02002995static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Takashi Iwai3af9ee62011-06-27 12:34:01 +02002996 hda_nid_t dac, const char *pfx)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02002997{
Takashi Iwai7085ec12009-10-02 09:03:58 +02002998 struct alc_spec *spec = codec->spec;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02002999 hda_nid_t sw, vol;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003000 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003001
3002 if (!pin)
3003 return 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003004 if (!dac) {
Takashi Iwai7085ec12009-10-02 09:03:58 +02003005 /* the corresponding DAC is already occupied */
3006 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
3007 return 0; /* no way */
3008 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02003009 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003010 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3011 }
3012
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003013 sw = alc_look_for_out_mute_nid(codec, pin, dac);
3014 vol = alc_look_for_out_vol_nid(codec, pin, dac);
3015 err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003016 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +02003017 return err;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003018 err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003019 if (err < 0)
3020 return err;
Takashi Iwai3af9ee62011-06-27 12:34:01 +02003021 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003022}
3023
Takashi Iwai343a04b2011-07-06 14:28:39 +02003024static int alc_auto_create_hp_out(struct hda_codec *codec)
3025{
3026 struct alc_spec *spec = codec->spec;
3027 return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3028 spec->multiout.hp_nid,
3029 "Headphone");
3030}
3031
3032static int alc_auto_create_speaker_out(struct hda_codec *codec)
3033{
3034 struct alc_spec *spec = codec->spec;
3035 return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
3036 spec->multiout.extra_out_nid[0],
3037 "Speaker");
3038}
3039
Takashi Iwai343a04b2011-07-06 14:28:39 +02003040static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003041 hda_nid_t pin, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003042 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003043{
Takashi Iwai7085ec12009-10-02 09:03:58 +02003044 int i, num;
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003045 hda_nid_t nid, mix = 0;
Takashi Iwaice503f32010-07-30 10:37:29 +02003046 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003047
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003048 alc_set_pin_output(codec, pin, pin_type);
3049 nid = alc_go_down_to_selector(codec, pin);
Takashi Iwai7085ec12009-10-02 09:03:58 +02003050 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
Takashi Iwai7085ec12009-10-02 09:03:58 +02003051 for (i = 0; i < num; i++) {
Takashi Iwai604401a2011-04-27 15:14:23 +02003052 if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
Takashi Iwai7085ec12009-10-02 09:03:58 +02003053 continue;
Takashi Iwaicd511552011-07-06 13:10:42 +02003054 mix = srcs[i];
3055 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003056 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003057 if (!mix)
3058 return;
3059
3060 /* need the manual connection? */
3061 if (num > 1)
3062 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
3063 /* unmute mixer widget inputs */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003064 if (nid_has_mute(codec, mix, HDA_INPUT)) {
3065 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003066 AMP_IN_UNMUTE(0));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003067 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaicd511552011-07-06 13:10:42 +02003068 AMP_IN_UNMUTE(1));
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003069 }
Takashi Iwaicd511552011-07-06 13:10:42 +02003070 /* initialize volume */
Takashi Iwaiafcd5512011-07-08 11:07:59 +02003071 nid = alc_look_for_out_vol_nid(codec, pin, dac);
3072 if (nid)
3073 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3074 AMP_OUT_ZERO);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003075}
3076
Takashi Iwai343a04b2011-07-06 14:28:39 +02003077static void alc_auto_init_multi_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003078{
3079 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +02003080 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003081 int i;
3082
3083 for (i = 0; i <= HDA_SIDE; i++) {
3084 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3085 if (nid)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003086 alc_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003087 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003088 }
3089}
3090
Takashi Iwai343a04b2011-07-06 14:28:39 +02003091static void alc_auto_init_extra_out(struct hda_codec *codec)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003092{
3093 struct alc_spec *spec = codec->spec;
3094 hda_nid_t pin;
3095
3096 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +02003097 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003098 alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003099 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01003100 pin = spec->autocfg.speaker_pins[0];
3101 if (pin)
Takashi Iwai343a04b2011-07-06 14:28:39 +02003102 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
Takashi Iwai7085ec12009-10-02 09:03:58 +02003103 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003104}
3105
Takashi Iwaice764ab2011-04-27 16:35:23 +02003106/*
3107 * multi-io helper
3108 */
3109static int alc_auto_fill_multi_ios(struct hda_codec *codec,
3110 unsigned int location)
3111{
3112 struct alc_spec *spec = codec->spec;
3113 struct auto_pin_cfg *cfg = &spec->autocfg;
3114 int type, i, num_pins = 0;
3115
3116 for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
3117 for (i = 0; i < cfg->num_inputs; i++) {
3118 hda_nid_t nid = cfg->inputs[i].pin;
3119 hda_nid_t dac;
3120 unsigned int defcfg, caps;
3121 if (cfg->inputs[i].type != type)
3122 continue;
3123 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3124 if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
3125 continue;
3126 if (location && get_defcfg_location(defcfg) != location)
3127 continue;
3128 caps = snd_hda_query_pin_caps(codec, nid);
3129 if (!(caps & AC_PINCAP_OUT))
3130 continue;
3131 dac = alc_auto_look_for_dac(codec, nid);
3132 if (!dac)
3133 continue;
3134 spec->multi_io[num_pins].pin = nid;
3135 spec->multi_io[num_pins].dac = dac;
3136 num_pins++;
Takashi Iwaidda14412011-05-02 11:29:30 +02003137 spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003138 }
3139 }
3140 spec->multiout.num_dacs = 1;
3141 if (num_pins < 2)
3142 return 0;
3143 return num_pins;
3144}
3145
3146static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
3147 struct snd_ctl_elem_info *uinfo)
3148{
3149 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3150 struct alc_spec *spec = codec->spec;
3151
3152 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3153 uinfo->count = 1;
3154 uinfo->value.enumerated.items = spec->multi_ios + 1;
3155 if (uinfo->value.enumerated.item > spec->multi_ios)
3156 uinfo->value.enumerated.item = spec->multi_ios;
3157 sprintf(uinfo->value.enumerated.name, "%dch",
3158 (uinfo->value.enumerated.item + 1) * 2);
3159 return 0;
3160}
3161
3162static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
3163 struct snd_ctl_elem_value *ucontrol)
3164{
3165 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3166 struct alc_spec *spec = codec->spec;
3167 ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
3168 return 0;
3169}
3170
3171static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
3172{
3173 struct alc_spec *spec = codec->spec;
3174 hda_nid_t nid = spec->multi_io[idx].pin;
3175
3176 if (!spec->multi_io[idx].ctl_in)
3177 spec->multi_io[idx].ctl_in =
3178 snd_hda_codec_read(codec, nid, 0,
3179 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3180 if (output) {
3181 snd_hda_codec_update_cache(codec, nid, 0,
3182 AC_VERB_SET_PIN_WIDGET_CONTROL,
3183 PIN_OUT);
3184 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3185 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3186 HDA_AMP_MUTE, 0);
3187 alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
3188 } else {
3189 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
3190 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3191 HDA_AMP_MUTE, HDA_AMP_MUTE);
3192 snd_hda_codec_update_cache(codec, nid, 0,
3193 AC_VERB_SET_PIN_WIDGET_CONTROL,
3194 spec->multi_io[idx].ctl_in);
3195 }
3196 return 0;
3197}
3198
3199static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
3200 struct snd_ctl_elem_value *ucontrol)
3201{
3202 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3203 struct alc_spec *spec = codec->spec;
3204 int i, ch;
3205
3206 ch = ucontrol->value.enumerated.item[0];
3207 if (ch < 0 || ch > spec->multi_ios)
3208 return -EINVAL;
3209 if (ch == (spec->ext_channel_count - 1) / 2)
3210 return 0;
3211 spec->ext_channel_count = (ch + 1) * 2;
3212 for (i = 0; i < spec->multi_ios; i++)
3213 alc_set_multi_io(codec, i, i < ch);
3214 spec->multiout.max_channels = spec->ext_channel_count;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003215 if (spec->need_dac_fix && !spec->const_channel_count)
3216 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
Takashi Iwaice764ab2011-04-27 16:35:23 +02003217 return 1;
3218}
3219
Takashi Iwaia9111322011-05-02 11:30:18 +02003220static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
Takashi Iwaice764ab2011-04-27 16:35:23 +02003221 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3222 .name = "Channel Mode",
3223 .info = alc_auto_ch_mode_info,
3224 .get = alc_auto_ch_mode_get,
3225 .put = alc_auto_ch_mode_put,
3226};
3227
Takashi Iwaicb053a82011-06-27 11:32:07 +02003228static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
3229 int (*fill_dac)(struct hda_codec *))
Takashi Iwaice764ab2011-04-27 16:35:23 +02003230{
3231 struct alc_spec *spec = codec->spec;
3232 struct auto_pin_cfg *cfg = &spec->autocfg;
3233 unsigned int location, defcfg;
3234 int num_pins;
3235
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003236 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
3237 /* use HP as primary out */
3238 cfg->speaker_outs = cfg->line_outs;
3239 memcpy(cfg->speaker_pins, cfg->line_out_pins,
3240 sizeof(cfg->speaker_pins));
3241 cfg->line_outs = cfg->hp_outs;
3242 memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3243 cfg->hp_outs = 0;
3244 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3245 cfg->line_out_type = AUTO_PIN_HP_OUT;
Takashi Iwaicb053a82011-06-27 11:32:07 +02003246 if (fill_dac)
3247 fill_dac(codec);
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003248 }
Takashi Iwaice764ab2011-04-27 16:35:23 +02003249 if (cfg->line_outs != 1 ||
Takashi Iwai3fccdfd2011-06-24 10:35:05 +02003250 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
Takashi Iwaice764ab2011-04-27 16:35:23 +02003251 return 0;
3252
3253 defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
3254 location = get_defcfg_location(defcfg);
3255
3256 num_pins = alc_auto_fill_multi_ios(codec, location);
3257 if (num_pins > 0) {
3258 struct snd_kcontrol_new *knew;
3259
3260 knew = alc_kcontrol_new(spec);
3261 if (!knew)
3262 return -ENOMEM;
3263 *knew = alc_auto_channel_mode_enum;
3264 knew->name = kstrdup("Channel Mode", GFP_KERNEL);
3265 if (!knew->name)
3266 return -ENOMEM;
3267
3268 spec->multi_ios = num_pins;
3269 spec->ext_channel_count = 2;
3270 spec->multiout.num_dacs = num_pins + 1;
3271 }
3272 return 0;
3273}
3274
Takashi Iwai1d045db2011-07-07 18:23:21 +02003275/* filter out invalid adc_nids (and capsrc_nids) that don't give all
3276 * active input pins
3277 */
3278static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
3279{
3280 struct alc_spec *spec = codec->spec;
3281 const struct hda_input_mux *imux;
3282 hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3283 hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
3284 int i, n, nums;
3285
3286 imux = spec->input_mux;
3287 if (!imux)
3288 return;
3289 if (spec->dyn_adc_switch)
3290 return;
3291
3292 nums = 0;
3293 for (n = 0; n < spec->num_adc_nids; n++) {
3294 hda_nid_t cap = spec->private_capsrc_nids[n];
3295 int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
3296 for (i = 0; i < imux->num_items; i++) {
3297 hda_nid_t pin = spec->imux_pins[i];
3298 if (pin) {
3299 if (get_connection_index(codec, cap, pin) < 0)
3300 break;
3301 } else if (num_conns <= imux->items[i].index)
3302 break;
3303 }
3304 if (i >= imux->num_items) {
3305 adc_nids[nums] = spec->private_adc_nids[n];
3306 capsrc_nids[nums++] = cap;
3307 }
3308 }
3309 if (!nums) {
3310 /* check whether ADC-switch is possible */
3311 if (!alc_check_dyn_adc_switch(codec)) {
3312 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
3313 " using fallback 0x%x\n",
3314 codec->chip_name, spec->private_adc_nids[0]);
3315 spec->num_adc_nids = 1;
3316 spec->auto_mic = 0;
3317 return;
3318 }
3319 } else if (nums != spec->num_adc_nids) {
3320 memcpy(spec->private_adc_nids, adc_nids,
3321 nums * sizeof(hda_nid_t));
3322 memcpy(spec->private_capsrc_nids, capsrc_nids,
3323 nums * sizeof(hda_nid_t));
3324 spec->num_adc_nids = nums;
3325 }
3326
3327 if (spec->auto_mic)
3328 alc_auto_mic_check_imux(codec); /* check auto-mic setups */
3329 else if (spec->input_mux->num_items == 1)
3330 spec->num_adc_nids = 1; /* reduce to a single ADC */
3331}
3332
3333/*
3334 * initialize ADC paths
3335 */
3336static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
3337{
3338 struct alc_spec *spec = codec->spec;
3339 hda_nid_t nid;
3340
3341 nid = spec->adc_nids[adc_idx];
3342 /* mute ADC */
Takashi Iwai44c02402011-07-08 15:14:19 +02003343 if (nid_has_mute(codec, nid, HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003344 snd_hda_codec_write(codec, nid, 0,
3345 AC_VERB_SET_AMP_GAIN_MUTE,
3346 AMP_IN_MUTE(0));
3347 return;
3348 }
3349 if (!spec->capsrc_nids)
3350 return;
3351 nid = spec->capsrc_nids[adc_idx];
Takashi Iwai44c02402011-07-08 15:14:19 +02003352 if (nid_has_mute(codec, nid, HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003353 snd_hda_codec_write(codec, nid, 0,
3354 AC_VERB_SET_AMP_GAIN_MUTE,
3355 AMP_OUT_MUTE);
3356}
3357
3358static void alc_auto_init_input_src(struct hda_codec *codec)
3359{
3360 struct alc_spec *spec = codec->spec;
3361 int c, nums;
3362
3363 for (c = 0; c < spec->num_adc_nids; c++)
3364 alc_auto_init_adc(codec, c);
3365 if (spec->dyn_adc_switch)
3366 nums = 1;
3367 else
3368 nums = spec->num_adc_nids;
3369 for (c = 0; c < nums; c++)
3370 alc_mux_select(codec, 0, spec->cur_mux[c], true);
3371}
3372
3373/* add mic boosts if needed */
3374static int alc_auto_add_mic_boost(struct hda_codec *codec)
3375{
3376 struct alc_spec *spec = codec->spec;
3377 struct auto_pin_cfg *cfg = &spec->autocfg;
3378 int i, err;
3379 int type_idx = 0;
3380 hda_nid_t nid;
3381 const char *prev_label = NULL;
3382
3383 for (i = 0; i < cfg->num_inputs; i++) {
3384 if (cfg->inputs[i].type > AUTO_PIN_MIC)
3385 break;
3386 nid = cfg->inputs[i].pin;
3387 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3388 const char *label;
3389 char boost_label[32];
3390
3391 label = hda_get_autocfg_input_label(codec, cfg, i);
3392 if (prev_label && !strcmp(label, prev_label))
3393 type_idx++;
3394 else
3395 type_idx = 0;
3396 prev_label = label;
3397
3398 snprintf(boost_label, sizeof(boost_label),
3399 "%s Boost Volume", label);
3400 err = add_control(spec, ALC_CTL_WIDGET_VOL,
3401 boost_label, type_idx,
3402 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
3403 if (err < 0)
3404 return err;
3405 }
3406 }
3407 return 0;
3408}
3409
3410/* select or unmute the given capsrc route */
3411static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
3412 int idx)
3413{
3414 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
3415 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
3416 HDA_AMP_MUTE, 0);
3417 } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
3418 snd_hda_codec_write_cache(codec, cap, 0,
3419 AC_VERB_SET_CONNECT_SEL, idx);
3420 }
3421}
3422
3423/* set the default connection to that pin */
3424static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
3425{
3426 struct alc_spec *spec = codec->spec;
3427 int i;
3428
3429 if (!pin)
3430 return 0;
3431 for (i = 0; i < spec->num_adc_nids; i++) {
3432 hda_nid_t cap = spec->capsrc_nids ?
3433 spec->capsrc_nids[i] : spec->adc_nids[i];
3434 int idx;
3435
3436 idx = get_connection_index(codec, cap, pin);
3437 if (idx < 0)
3438 continue;
3439 select_or_unmute_capsrc(codec, cap, idx);
3440 return i; /* return the found index */
3441 }
3442 return -1; /* not found */
3443}
3444
3445/* initialize some special cases for input sources */
3446static void alc_init_special_input_src(struct hda_codec *codec)
3447{
3448 struct alc_spec *spec = codec->spec;
3449 int i;
3450
3451 for (i = 0; i < spec->autocfg.num_inputs; i++)
3452 init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
3453}
3454
3455/* assign appropriate capture mixers */
3456static void set_capture_mixer(struct hda_codec *codec)
3457{
3458 struct alc_spec *spec = codec->spec;
3459 static const struct snd_kcontrol_new *caps[2][3] = {
3460 { alc_capture_mixer_nosrc1,
3461 alc_capture_mixer_nosrc2,
3462 alc_capture_mixer_nosrc3 },
3463 { alc_capture_mixer1,
3464 alc_capture_mixer2,
3465 alc_capture_mixer3 },
3466 };
3467
3468 /* check whether either of ADC or MUX has a volume control */
Takashi Iwai44c02402011-07-08 15:14:19 +02003469 if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003470 if (!spec->capsrc_nids)
3471 return; /* no volume */
Takashi Iwai44c02402011-07-08 15:14:19 +02003472 if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003473 return; /* no volume in capsrc, too */
3474 spec->vol_in_capsrc = 1;
3475 }
3476
3477 if (spec->num_adc_nids > 0) {
3478 int mux = 0;
3479 int num_adcs = 0;
3480
3481 if (spec->input_mux && spec->input_mux->num_items > 1)
3482 mux = 1;
3483 if (spec->auto_mic) {
3484 num_adcs = 1;
3485 mux = 0;
3486 } else if (spec->dyn_adc_switch)
3487 num_adcs = 1;
3488 if (!num_adcs) {
3489 if (spec->num_adc_nids > 3)
3490 spec->num_adc_nids = 3;
3491 else if (!spec->num_adc_nids)
3492 return;
3493 num_adcs = spec->num_adc_nids;
3494 }
3495 spec->cap_mixer = caps[mux][num_adcs - 1];
3496 }
3497}
3498
3499/*
Takashi Iwaie4770622011-07-08 11:11:35 +02003500 * standard auto-parser initializations
3501 */
3502static void alc_auto_init_std(struct hda_codec *codec)
3503{
3504 struct alc_spec *spec = codec->spec;
3505 alc_auto_init_multi_out(codec);
3506 alc_auto_init_extra_out(codec);
3507 alc_auto_init_analog_input(codec);
3508 alc_auto_init_input_src(codec);
3509 alc_auto_init_digital(codec);
3510 if (spec->unsol_event)
3511 alc_inithook(codec);
3512}
3513
3514/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02003515 * Digital-beep handlers
3516 */
3517#ifdef CONFIG_SND_HDA_INPUT_BEEP
3518#define set_beep_amp(spec, nid, idx, dir) \
3519 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
3520
3521static const struct snd_pci_quirk beep_white_list[] = {
3522 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
3523 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
3524 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
3525 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
3526 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
3527 {}
3528};
3529
3530static inline int has_cdefine_beep(struct hda_codec *codec)
3531{
3532 struct alc_spec *spec = codec->spec;
3533 const struct snd_pci_quirk *q;
3534 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
3535 if (q)
3536 return q->value;
3537 return spec->cdefine.enable_pcbeep;
3538}
3539#else
3540#define set_beep_amp(spec, nid, idx, dir) /* NOP */
3541#define has_cdefine_beep(codec) 0
3542#endif
3543
3544/* parse the BIOS configuration and set up the alc_spec */
3545/* return 1 if successful, 0 if the proper config is not found,
3546 * or a negative error code
3547 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003548static int alc_parse_auto_config(struct hda_codec *codec,
3549 const hda_nid_t *ignore_nids,
3550 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003551{
3552 struct alc_spec *spec = codec->spec;
3553 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003554
3555 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003556 ignore_nids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003557 if (err < 0)
3558 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003559 if (!spec->autocfg.line_outs) {
3560 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
3561 spec->multiout.max_channels = 2;
3562 spec->no_analog = 1;
3563 goto dig_only;
3564 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003565 return 0; /* can't find valid BIOS pin config */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003566 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003567 err = alc_auto_fill_dac_nids(codec);
3568 if (err < 0)
3569 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003570 err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
3571 if (err < 0)
3572 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003573 err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
3574 if (err < 0)
3575 return err;
3576 err = alc_auto_create_hp_out(codec);
3577 if (err < 0)
3578 return err;
3579 err = alc_auto_create_speaker_out(codec);
3580 if (err < 0)
3581 return err;
3582 err = alc_auto_create_input_ctls(codec);
3583 if (err < 0)
3584 return err;
3585
3586 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3587
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003588 dig_only:
Takashi Iwai1d045db2011-07-07 18:23:21 +02003589 alc_auto_parse_digital(codec);
3590
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003591 if (!spec->no_analog)
3592 alc_remove_invalid_adc_nids(codec);
3593
3594 if (ssid_nids)
3595 alc_ssid_check(codec, ssid_nids);
3596
3597 if (!spec->no_analog) {
3598 alc_auto_check_switches(codec);
3599 err = alc_auto_add_mic_boost(codec);
3600 if (err < 0)
3601 return err;
3602 }
3603
Takashi Iwai1d045db2011-07-07 18:23:21 +02003604 if (spec->kctls.list)
3605 add_mixer(spec, spec->kctls.list);
3606
Takashi Iwai1d045db2011-07-07 18:23:21 +02003607 return 1;
3608}
3609
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003610static int alc880_parse_auto_config(struct hda_codec *codec)
3611{
3612 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
3613 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3614 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
3615}
3616
Takashi Iwai1d045db2011-07-07 18:23:21 +02003617#ifdef CONFIG_SND_HDA_POWER_SAVE
3618static const struct hda_amp_list alc880_loopbacks[] = {
3619 { 0x0b, HDA_INPUT, 0 },
3620 { 0x0b, HDA_INPUT, 1 },
3621 { 0x0b, HDA_INPUT, 2 },
3622 { 0x0b, HDA_INPUT, 3 },
3623 { 0x0b, HDA_INPUT, 4 },
3624 { } /* end */
3625};
3626#endif
3627
3628/*
3629 * board setups
3630 */
3631#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3632#define alc_board_config \
3633 snd_hda_check_board_config
3634#define alc_board_codec_sid_config \
3635 snd_hda_check_board_codec_sid_config
3636#include "alc_quirks.c"
3637#else
3638#define alc_board_config(codec, nums, models, tbl) -1
3639#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
3640#define setup_preset(codec, x) /* NOP */
3641#endif
3642
3643/*
3644 * OK, here we have finally the patch for ALC880
3645 */
3646#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3647#include "alc880_quirks.c"
3648#endif
3649
3650static int patch_alc880(struct hda_codec *codec)
3651{
3652 struct alc_spec *spec;
3653 int board_config;
3654 int err;
3655
3656 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3657 if (spec == NULL)
3658 return -ENOMEM;
3659
3660 codec->spec = spec;
3661
3662 spec->mixer_nid = 0x0b;
Takashi Iwai7b1655f2011-07-14 15:31:21 +02003663 spec->need_dac_fix = 1;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003664
3665 board_config = alc_board_config(codec, ALC880_MODEL_LAST,
3666 alc880_models, alc880_cfg_tbl);
3667 if (board_config < 0) {
3668 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3669 codec->chip_name);
3670 board_config = ALC_MODEL_AUTO;
3671 }
3672
3673 if (board_config == ALC_MODEL_AUTO) {
3674 /* automatic parse from the BIOS config */
3675 err = alc880_parse_auto_config(codec);
3676 if (err < 0) {
3677 alc_free(codec);
3678 return err;
3679 }
3680#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3681 else if (!err) {
3682 printk(KERN_INFO
3683 "hda_codec: Cannot set up configuration "
3684 "from BIOS. Using 3-stack mode...\n");
3685 board_config = ALC880_3ST;
3686 }
3687#endif
3688 }
3689
Takashi Iwai1d045db2011-07-07 18:23:21 +02003690 if (board_config != ALC_MODEL_AUTO)
3691 setup_preset(codec, &alc880_presets[board_config]);
3692
Takashi Iwai60a6a842011-07-27 14:01:24 +02003693 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003694 alc_auto_fill_adc_caps(codec);
3695 alc_rebuild_imux_for_auto_mic(codec);
3696 alc_remove_invalid_adc_nids(codec);
3697 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003698
3699 if (!spec->no_analog && !spec->cap_mixer)
3700 set_capture_mixer(codec);
3701
3702 if (!spec->no_analog) {
3703 err = snd_hda_attach_beep_device(codec, 0x1);
3704 if (err < 0) {
3705 alc_free(codec);
3706 return err;
3707 }
3708 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
3709 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003710
3711 spec->vmaster_nid = 0x0c;
3712
3713 codec->patch_ops = alc_patch_ops;
3714 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02003715 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003716#ifdef CONFIG_SND_HDA_POWER_SAVE
3717 if (!spec->loopback.amplist)
3718 spec->loopback.amplist = alc880_loopbacks;
3719#endif
3720
3721 return 0;
3722}
3723
3724
3725/*
3726 * ALC260 support
3727 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003728static int alc260_parse_auto_config(struct hda_codec *codec)
3729{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003730 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003731 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
3732 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003733}
3734
Takashi Iwai1d045db2011-07-07 18:23:21 +02003735#ifdef CONFIG_SND_HDA_POWER_SAVE
3736static const struct hda_amp_list alc260_loopbacks[] = {
3737 { 0x07, HDA_INPUT, 0 },
3738 { 0x07, HDA_INPUT, 1 },
3739 { 0x07, HDA_INPUT, 2 },
3740 { 0x07, HDA_INPUT, 3 },
3741 { 0x07, HDA_INPUT, 4 },
3742 { } /* end */
3743};
3744#endif
3745
3746/*
3747 * Pin config fixes
3748 */
3749enum {
3750 PINFIX_HP_DC5750,
3751};
3752
3753static const struct alc_fixup alc260_fixups[] = {
3754 [PINFIX_HP_DC5750] = {
3755 .type = ALC_FIXUP_PINS,
3756 .v.pins = (const struct alc_pincfg[]) {
3757 { 0x11, 0x90130110 }, /* speaker */
3758 { }
3759 }
3760 },
3761};
3762
3763static const struct snd_pci_quirk alc260_fixup_tbl[] = {
3764 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
3765 {}
3766};
3767
3768/*
3769 */
3770#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3771#include "alc260_quirks.c"
3772#endif
3773
3774static int patch_alc260(struct hda_codec *codec)
3775{
3776 struct alc_spec *spec;
3777 int err, board_config;
3778
3779 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3780 if (spec == NULL)
3781 return -ENOMEM;
3782
3783 codec->spec = spec;
3784
3785 spec->mixer_nid = 0x07;
3786
3787 board_config = alc_board_config(codec, ALC260_MODEL_LAST,
3788 alc260_models, alc260_cfg_tbl);
3789 if (board_config < 0) {
3790 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3791 codec->chip_name);
3792 board_config = ALC_MODEL_AUTO;
3793 }
3794
3795 if (board_config == ALC_MODEL_AUTO) {
3796 alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
3797 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3798 }
3799
3800 if (board_config == ALC_MODEL_AUTO) {
3801 /* automatic parse from the BIOS config */
3802 err = alc260_parse_auto_config(codec);
3803 if (err < 0) {
3804 alc_free(codec);
3805 return err;
3806 }
3807#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3808 else if (!err) {
3809 printk(KERN_INFO
3810 "hda_codec: Cannot set up configuration "
3811 "from BIOS. Using base mode...\n");
3812 board_config = ALC260_BASIC;
3813 }
3814#endif
3815 }
3816
Takashi Iwai1d045db2011-07-07 18:23:21 +02003817 if (board_config != ALC_MODEL_AUTO)
3818 setup_preset(codec, &alc260_presets[board_config]);
3819
Takashi Iwai60a6a842011-07-27 14:01:24 +02003820 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003821 alc_auto_fill_adc_caps(codec);
3822 alc_rebuild_imux_for_auto_mic(codec);
3823 alc_remove_invalid_adc_nids(codec);
3824 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003825
3826 if (!spec->no_analog && !spec->cap_mixer)
3827 set_capture_mixer(codec);
3828
3829 if (!spec->no_analog) {
3830 err = snd_hda_attach_beep_device(codec, 0x1);
3831 if (err < 0) {
3832 alc_free(codec);
3833 return err;
3834 }
3835 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
3836 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02003837
3838 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
3839
3840 spec->vmaster_nid = 0x08;
3841
3842 codec->patch_ops = alc_patch_ops;
3843 if (board_config == ALC_MODEL_AUTO)
Takashi Iwai8452a982011-07-08 16:19:48 +02003844 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003845 spec->shutup = alc_eapd_shutup;
3846#ifdef CONFIG_SND_HDA_POWER_SAVE
3847 if (!spec->loopback.amplist)
3848 spec->loopback.amplist = alc260_loopbacks;
3849#endif
3850
3851 return 0;
3852}
3853
3854
3855/*
3856 * ALC882/883/885/888/889 support
3857 *
3858 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
3859 * configuration. Each pin widget can choose any input DACs and a mixer.
3860 * Each ADC is connected from a mixer of all inputs. This makes possible
3861 * 6-channel independent captures.
3862 *
3863 * In addition, an independent DAC for the multi-playback (not used in this
3864 * driver yet).
3865 */
3866#ifdef CONFIG_SND_HDA_POWER_SAVE
3867#define alc882_loopbacks alc880_loopbacks
3868#endif
3869
3870/*
3871 * Pin config fixes
3872 */
3873enum {
3874 PINFIX_ABIT_AW9D_MAX,
3875 PINFIX_LENOVO_Y530,
3876 PINFIX_PB_M5210,
3877 PINFIX_ACER_ASPIRE_7736,
3878};
3879
3880static const struct alc_fixup alc882_fixups[] = {
3881 [PINFIX_ABIT_AW9D_MAX] = {
3882 .type = ALC_FIXUP_PINS,
3883 .v.pins = (const struct alc_pincfg[]) {
3884 { 0x15, 0x01080104 }, /* side */
3885 { 0x16, 0x01011012 }, /* rear */
3886 { 0x17, 0x01016011 }, /* clfe */
3887 { }
3888 }
3889 },
3890 [PINFIX_LENOVO_Y530] = {
3891 .type = ALC_FIXUP_PINS,
3892 .v.pins = (const struct alc_pincfg[]) {
3893 { 0x15, 0x99130112 }, /* rear int speakers */
3894 { 0x16, 0x99130111 }, /* subwoofer */
3895 { }
3896 }
3897 },
3898 [PINFIX_PB_M5210] = {
3899 .type = ALC_FIXUP_VERBS,
3900 .v.verbs = (const struct hda_verb[]) {
3901 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
3902 {}
3903 }
3904 },
3905 [PINFIX_ACER_ASPIRE_7736] = {
3906 .type = ALC_FIXUP_SKU,
3907 .v.sku = ALC_FIXUP_SKU_IGNORE,
3908 },
3909};
3910
3911static const struct snd_pci_quirk alc882_fixup_tbl[] = {
3912 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
3913 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
3914 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
3915 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
3916 {}
3917};
3918
3919/*
3920 * BIOS auto configuration
3921 */
3922/* almost identical with ALC880 parser... */
3923static int alc882_parse_auto_config(struct hda_codec *codec)
3924{
Takashi Iwai1d045db2011-07-07 18:23:21 +02003925 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02003926 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3927 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003928}
3929
Takashi Iwai1d045db2011-07-07 18:23:21 +02003930/*
3931 */
3932#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3933#include "alc882_quirks.c"
3934#endif
3935
3936static int patch_alc882(struct hda_codec *codec)
3937{
3938 struct alc_spec *spec;
3939 int err, board_config;
3940
3941 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3942 if (spec == NULL)
3943 return -ENOMEM;
3944
3945 codec->spec = spec;
3946
3947 spec->mixer_nid = 0x0b;
3948
3949 switch (codec->vendor_id) {
3950 case 0x10ec0882:
3951 case 0x10ec0885:
3952 break;
3953 default:
3954 /* ALC883 and variants */
3955 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
3956 break;
3957 }
3958
3959 board_config = alc_board_config(codec, ALC882_MODEL_LAST,
3960 alc882_models, alc882_cfg_tbl);
3961
3962 if (board_config < 0)
3963 board_config = alc_board_codec_sid_config(codec,
3964 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
3965
3966 if (board_config < 0) {
3967 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3968 codec->chip_name);
3969 board_config = ALC_MODEL_AUTO;
3970 }
3971
3972 if (board_config == ALC_MODEL_AUTO) {
3973 alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
3974 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
3975 }
3976
3977 alc_auto_parse_customize_define(codec);
3978
3979 if (board_config == ALC_MODEL_AUTO) {
3980 /* automatic parse from the BIOS config */
3981 err = alc882_parse_auto_config(codec);
3982 if (err < 0) {
3983 alc_free(codec);
3984 return err;
3985 }
3986#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
3987 else if (!err) {
3988 printk(KERN_INFO
3989 "hda_codec: Cannot set up configuration "
3990 "from BIOS. Using base mode...\n");
3991 board_config = ALC882_3ST_DIG;
3992 }
3993#endif
3994 }
3995
Takashi Iwai1d045db2011-07-07 18:23:21 +02003996 if (board_config != ALC_MODEL_AUTO)
3997 setup_preset(codec, &alc882_presets[board_config]);
3998
Takashi Iwai60a6a842011-07-27 14:01:24 +02003999 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004000 alc_auto_fill_adc_caps(codec);
4001 alc_rebuild_imux_for_auto_mic(codec);
4002 alc_remove_invalid_adc_nids(codec);
4003 }
4004
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004005 if (!spec->no_analog && !spec->cap_mixer)
4006 set_capture_mixer(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004007
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004008 if (!spec->no_analog && has_cdefine_beep(codec)) {
4009 err = snd_hda_attach_beep_device(codec, 0x1);
4010 if (err < 0) {
4011 alc_free(codec);
4012 return err;
4013 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004014 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004015 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004016
4017 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4018
4019 spec->vmaster_nid = 0x0c;
4020
4021 codec->patch_ops = alc_patch_ops;
4022 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004023 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004024
4025 alc_init_jacks(codec);
4026#ifdef CONFIG_SND_HDA_POWER_SAVE
4027 if (!spec->loopback.amplist)
4028 spec->loopback.amplist = alc882_loopbacks;
4029#endif
4030
4031 return 0;
4032}
4033
4034
4035/*
4036 * ALC262 support
4037 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004038static int alc262_parse_auto_config(struct hda_codec *codec)
4039{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004040 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004041 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4042 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004043}
4044
4045/*
4046 * Pin config fixes
4047 */
4048enum {
4049 PINFIX_FSC_H270,
4050 PINFIX_HP_Z200,
4051};
4052
4053static const struct alc_fixup alc262_fixups[] = {
4054 [PINFIX_FSC_H270] = {
4055 .type = ALC_FIXUP_PINS,
4056 .v.pins = (const struct alc_pincfg[]) {
4057 { 0x14, 0x99130110 }, /* speaker */
4058 { 0x15, 0x0221142f }, /* front HP */
4059 { 0x1b, 0x0121141f }, /* rear HP */
4060 { }
4061 }
4062 },
4063 [PINFIX_HP_Z200] = {
4064 .type = ALC_FIXUP_PINS,
4065 .v.pins = (const struct alc_pincfg[]) {
4066 { 0x16, 0x99130120 }, /* internal speaker */
4067 { }
4068 }
4069 },
4070};
4071
4072static const struct snd_pci_quirk alc262_fixup_tbl[] = {
4073 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
4074 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
4075 {}
4076};
4077
4078
4079#ifdef CONFIG_SND_HDA_POWER_SAVE
4080#define alc262_loopbacks alc880_loopbacks
4081#endif
4082
Takashi Iwai1d045db2011-07-07 18:23:21 +02004083/*
4084 */
4085#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4086#include "alc262_quirks.c"
4087#endif
4088
4089static int patch_alc262(struct hda_codec *codec)
4090{
4091 struct alc_spec *spec;
4092 int board_config;
4093 int err;
4094
4095 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4096 if (spec == NULL)
4097 return -ENOMEM;
4098
4099 codec->spec = spec;
4100
4101 spec->mixer_nid = 0x0b;
4102
4103#if 0
4104 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
4105 * under-run
4106 */
4107 {
4108 int tmp;
4109 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4110 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
4111 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
4112 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
4113 }
4114#endif
4115 alc_auto_parse_customize_define(codec);
4116
4117 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
4118
4119 board_config = alc_board_config(codec, ALC262_MODEL_LAST,
4120 alc262_models, alc262_cfg_tbl);
4121
4122 if (board_config < 0) {
4123 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4124 codec->chip_name);
4125 board_config = ALC_MODEL_AUTO;
4126 }
4127
4128 if (board_config == ALC_MODEL_AUTO) {
4129 alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
4130 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4131 }
4132
4133 if (board_config == ALC_MODEL_AUTO) {
4134 /* automatic parse from the BIOS config */
4135 err = alc262_parse_auto_config(codec);
4136 if (err < 0) {
4137 alc_free(codec);
4138 return err;
4139 }
4140#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4141 else if (!err) {
4142 printk(KERN_INFO
4143 "hda_codec: Cannot set up configuration "
4144 "from BIOS. Using base mode...\n");
4145 board_config = ALC262_BASIC;
4146 }
4147#endif
4148 }
4149
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004150 if (board_config != ALC_MODEL_AUTO)
4151 setup_preset(codec, &alc262_presets[board_config]);
4152
Takashi Iwai60a6a842011-07-27 14:01:24 +02004153 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004154 alc_auto_fill_adc_caps(codec);
4155 alc_rebuild_imux_for_auto_mic(codec);
4156 alc_remove_invalid_adc_nids(codec);
4157 }
4158
4159 if (!spec->no_analog && !spec->cap_mixer)
4160 set_capture_mixer(codec);
4161
Takashi Iwai1d045db2011-07-07 18:23:21 +02004162 if (!spec->no_analog && has_cdefine_beep(codec)) {
4163 err = snd_hda_attach_beep_device(codec, 0x1);
4164 if (err < 0) {
4165 alc_free(codec);
4166 return err;
4167 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004168 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004169 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004170
4171 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4172
4173 spec->vmaster_nid = 0x0c;
4174
4175 codec->patch_ops = alc_patch_ops;
4176 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02004177 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004178 spec->shutup = alc_eapd_shutup;
4179
4180 alc_init_jacks(codec);
4181#ifdef CONFIG_SND_HDA_POWER_SAVE
4182 if (!spec->loopback.amplist)
4183 spec->loopback.amplist = alc262_loopbacks;
4184#endif
4185
4186 return 0;
4187}
4188
4189/*
4190 * ALC268
4191 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004192/* bind Beep switches of both NID 0x0f and 0x10 */
4193static const struct hda_bind_ctls alc268_bind_beep_sw = {
4194 .ops = &snd_hda_bind_sw,
4195 .values = {
4196 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
4197 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
4198 0
4199 },
4200};
4201
4202static const struct snd_kcontrol_new alc268_beep_mixer[] = {
4203 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
4204 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
4205 { }
4206};
4207
4208/* set PCBEEP vol = 0, mute connections */
4209static const struct hda_verb alc268_beep_init_verbs[] = {
4210 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4211 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4212 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4213 { }
4214};
4215
4216/*
4217 * BIOS auto configuration
4218 */
4219static int alc268_parse_auto_config(struct hda_codec *codec)
4220{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004221 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai1d045db2011-07-07 18:23:21 +02004222 struct alc_spec *spec = codec->spec;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004223 int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
4224 if (err > 0) {
4225 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
4226 add_mixer(spec, alc268_beep_mixer);
4227 add_verb(spec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004228 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004229 }
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004230 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004231}
4232
Takashi Iwai1d045db2011-07-07 18:23:21 +02004233/*
4234 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004235static int patch_alc268(struct hda_codec *codec)
4236{
4237 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004238 int i, has_beep, err;
4239
4240 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4241 if (spec == NULL)
4242 return -ENOMEM;
4243
4244 codec->spec = spec;
4245
4246 /* ALC268 has no aa-loopback mixer */
4247
Takashi Iwai6ebb8052011-08-16 15:15:40 +02004248 /* automatic parse from the BIOS config */
4249 err = alc268_parse_auto_config(codec);
4250 if (err < 0) {
4251 alc_free(codec);
4252 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004253 }
4254
Takashi Iwai1d045db2011-07-07 18:23:21 +02004255 has_beep = 0;
4256 for (i = 0; i < spec->num_mixers; i++) {
4257 if (spec->mixers[i] == alc268_beep_mixer) {
4258 has_beep = 1;
4259 break;
4260 }
4261 }
4262
4263 if (has_beep) {
4264 err = snd_hda_attach_beep_device(codec, 0x1);
4265 if (err < 0) {
4266 alc_free(codec);
4267 return err;
4268 }
4269 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
4270 /* override the amp caps for beep generator */
4271 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
4272 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
4273 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
4274 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4275 (0 << AC_AMPCAP_MUTE_SHIFT));
4276 }
4277
Takashi Iwai60a6a842011-07-27 14:01:24 +02004278 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004279 alc_auto_fill_adc_caps(codec);
4280 alc_rebuild_imux_for_auto_mic(codec);
4281 alc_remove_invalid_adc_nids(codec);
4282 }
4283
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004284 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004285 set_capture_mixer(codec);
4286
4287 spec->vmaster_nid = 0x02;
4288
4289 codec->patch_ops = alc_patch_ops;
Takashi Iwai6ebb8052011-08-16 15:15:40 +02004290 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004291 spec->shutup = alc_eapd_shutup;
4292
4293 alc_init_jacks(codec);
4294
4295 return 0;
4296}
4297
4298/*
4299 * ALC269
4300 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004301#ifdef CONFIG_SND_HDA_POWER_SAVE
4302#define alc269_loopbacks alc880_loopbacks
4303#endif
4304
4305static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
4306 .substreams = 1,
4307 .channels_min = 2,
4308 .channels_max = 8,
4309 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4310 /* NID is set in alc_build_pcms */
4311 .ops = {
4312 .open = alc_playback_pcm_open,
4313 .prepare = alc_playback_pcm_prepare,
4314 .cleanup = alc_playback_pcm_cleanup
4315 },
4316};
4317
4318static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
4319 .substreams = 1,
4320 .channels_min = 2,
4321 .channels_max = 2,
4322 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
4323 /* NID is set in alc_build_pcms */
4324};
4325
4326#ifdef CONFIG_SND_HDA_POWER_SAVE
4327static int alc269_mic2_for_mute_led(struct hda_codec *codec)
4328{
4329 switch (codec->subsystem_id) {
4330 case 0x103c1586:
4331 return 1;
4332 }
4333 return 0;
4334}
4335
4336static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
4337{
4338 /* update mute-LED according to the speaker mute state */
4339 if (nid == 0x01 || nid == 0x14) {
4340 int pinval;
4341 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
4342 HDA_AMP_MUTE)
4343 pinval = 0x24;
4344 else
4345 pinval = 0x20;
4346 /* mic2 vref pin is used for mute LED control */
4347 snd_hda_codec_update_cache(codec, 0x19, 0,
4348 AC_VERB_SET_PIN_WIDGET_CONTROL,
4349 pinval);
4350 }
4351 return alc_check_power_status(codec, nid);
4352}
4353#endif /* CONFIG_SND_HDA_POWER_SAVE */
4354
4355/* different alc269-variants */
4356enum {
4357 ALC269_TYPE_ALC269VA,
4358 ALC269_TYPE_ALC269VB,
4359 ALC269_TYPE_ALC269VC,
4360};
4361
4362/*
4363 * BIOS auto configuration
4364 */
4365static int alc269_parse_auto_config(struct hda_codec *codec)
4366{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004367 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004368 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
4369 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4370 struct alc_spec *spec = codec->spec;
4371 const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
4372 alc269va_ssids : alc269_ssids;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004373
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004374 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004375}
4376
Takashi Iwai1d045db2011-07-07 18:23:21 +02004377static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
4378{
4379 int val = alc_read_coef_idx(codec, 0x04);
4380 if (power_up)
4381 val |= 1 << 11;
4382 else
4383 val &= ~(1 << 11);
4384 alc_write_coef_idx(codec, 0x04, val);
4385}
4386
4387static void alc269_shutup(struct hda_codec *codec)
4388{
4389 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
4390 alc269_toggle_power_output(codec, 0);
4391 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4392 alc269_toggle_power_output(codec, 0);
4393 msleep(150);
4394 }
4395}
4396
Takashi Iwai2a439522011-07-26 09:52:50 +02004397#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004398static int alc269_resume(struct hda_codec *codec)
4399{
4400 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4401 alc269_toggle_power_output(codec, 0);
4402 msleep(150);
4403 }
4404
4405 codec->patch_ops.init(codec);
4406
4407 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4408 alc269_toggle_power_output(codec, 1);
4409 msleep(200);
4410 }
4411
4412 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
4413 alc269_toggle_power_output(codec, 1);
4414
4415 snd_hda_codec_resume_amp(codec);
4416 snd_hda_codec_resume_cache(codec);
4417 hda_call_check_power_status(codec, 0x01);
4418 return 0;
4419}
Takashi Iwai2a439522011-07-26 09:52:50 +02004420#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02004421
4422static void alc269_fixup_hweq(struct hda_codec *codec,
4423 const struct alc_fixup *fix, int action)
4424{
4425 int coef;
4426
4427 if (action != ALC_FIXUP_ACT_INIT)
4428 return;
4429 coef = alc_read_coef_idx(codec, 0x1e);
4430 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
4431}
4432
4433static void alc271_fixup_dmic(struct hda_codec *codec,
4434 const struct alc_fixup *fix, int action)
4435{
4436 static const struct hda_verb verbs[] = {
4437 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
4438 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
4439 {}
4440 };
4441 unsigned int cfg;
4442
4443 if (strcmp(codec->chip_name, "ALC271X"))
4444 return;
4445 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
4446 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
4447 snd_hda_sequence_write(codec, verbs);
4448}
4449
Takashi Iwai017f2a12011-07-09 14:42:25 +02004450static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4451 const struct alc_fixup *fix, int action)
4452{
4453 struct alc_spec *spec = codec->spec;
4454
4455 if (action != ALC_FIXUP_ACT_PROBE)
4456 return;
4457
4458 /* Due to a hardware problem on Lenovo Ideadpad, we need to
4459 * fix the sample rate of analog I/O to 44.1kHz
4460 */
4461 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
4462 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4463}
4464
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004465static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4466 const struct alc_fixup *fix, int action)
4467{
4468 int coef;
4469
4470 if (action != ALC_FIXUP_ACT_INIT)
4471 return;
4472 /* The digital-mic unit sends PDM (differential signal) instead of
4473 * the standard PCM, thus you can't record a valid mono stream as is.
4474 * Below is a workaround specific to ALC269 to control the dmic
4475 * signal source as mono.
4476 */
4477 coef = alc_read_coef_idx(codec, 0x07);
4478 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4479}
4480
Takashi Iwai24519912011-08-16 15:08:49 +02004481static void alc269_quanta_automute(struct hda_codec *codec)
4482{
4483 update_speakers(codec);
4484
4485 snd_hda_codec_write(codec, 0x20, 0,
4486 AC_VERB_SET_COEF_INDEX, 0x0c);
4487 snd_hda_codec_write(codec, 0x20, 0,
4488 AC_VERB_SET_PROC_COEF, 0x680);
4489
4490 snd_hda_codec_write(codec, 0x20, 0,
4491 AC_VERB_SET_COEF_INDEX, 0x0c);
4492 snd_hda_codec_write(codec, 0x20, 0,
4493 AC_VERB_SET_PROC_COEF, 0x480);
4494}
4495
4496static void alc269_fixup_quanta_mute(struct hda_codec *codec,
4497 const struct alc_fixup *fix, int action)
4498{
4499 struct alc_spec *spec = codec->spec;
4500 if (action != ALC_FIXUP_ACT_PROBE)
4501 return;
4502 spec->automute_hook = alc269_quanta_automute;
4503}
4504
Takashi Iwai1d045db2011-07-07 18:23:21 +02004505enum {
4506 ALC269_FIXUP_SONY_VAIO,
4507 ALC275_FIXUP_SONY_VAIO_GPIO2,
4508 ALC269_FIXUP_DELL_M101Z,
4509 ALC269_FIXUP_SKU_IGNORE,
4510 ALC269_FIXUP_ASUS_G73JW,
4511 ALC269_FIXUP_LENOVO_EAPD,
4512 ALC275_FIXUP_SONY_HWEQ,
4513 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004514 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004515 ALC269_FIXUP_STEREO_DMIC,
Takashi Iwai24519912011-08-16 15:08:49 +02004516 ALC269_FIXUP_QUANTA_MUTE,
4517 ALC269_FIXUP_LIFEBOOK,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004518};
4519
4520static const struct alc_fixup alc269_fixups[] = {
4521 [ALC269_FIXUP_SONY_VAIO] = {
4522 .type = ALC_FIXUP_VERBS,
4523 .v.verbs = (const struct hda_verb[]) {
4524 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
4525 {}
4526 }
4527 },
4528 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
4529 .type = ALC_FIXUP_VERBS,
4530 .v.verbs = (const struct hda_verb[]) {
4531 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4532 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4533 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4534 { }
4535 },
4536 .chained = true,
4537 .chain_id = ALC269_FIXUP_SONY_VAIO
4538 },
4539 [ALC269_FIXUP_DELL_M101Z] = {
4540 .type = ALC_FIXUP_VERBS,
4541 .v.verbs = (const struct hda_verb[]) {
4542 /* Enables internal speaker */
4543 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4544 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4545 {}
4546 }
4547 },
4548 [ALC269_FIXUP_SKU_IGNORE] = {
4549 .type = ALC_FIXUP_SKU,
4550 .v.sku = ALC_FIXUP_SKU_IGNORE,
4551 },
4552 [ALC269_FIXUP_ASUS_G73JW] = {
4553 .type = ALC_FIXUP_PINS,
4554 .v.pins = (const struct alc_pincfg[]) {
4555 { 0x17, 0x99130111 }, /* subwoofer */
4556 { }
4557 }
4558 },
4559 [ALC269_FIXUP_LENOVO_EAPD] = {
4560 .type = ALC_FIXUP_VERBS,
4561 .v.verbs = (const struct hda_verb[]) {
4562 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4563 {}
4564 }
4565 },
4566 [ALC275_FIXUP_SONY_HWEQ] = {
4567 .type = ALC_FIXUP_FUNC,
4568 .v.func = alc269_fixup_hweq,
4569 .chained = true,
4570 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4571 },
4572 [ALC271_FIXUP_DMIC] = {
4573 .type = ALC_FIXUP_FUNC,
4574 .v.func = alc271_fixup_dmic,
4575 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004576 [ALC269_FIXUP_PCM_44K] = {
4577 .type = ALC_FIXUP_FUNC,
4578 .v.func = alc269_fixup_pcm_44k,
4579 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004580 [ALC269_FIXUP_STEREO_DMIC] = {
4581 .type = ALC_FIXUP_FUNC,
4582 .v.func = alc269_fixup_stereo_dmic,
4583 },
Takashi Iwai24519912011-08-16 15:08:49 +02004584 [ALC269_FIXUP_QUANTA_MUTE] = {
4585 .type = ALC_FIXUP_FUNC,
4586 .v.func = alc269_fixup_quanta_mute,
4587 },
4588 [ALC269_FIXUP_LIFEBOOK] = {
4589 .type = ALC_FIXUP_PINS,
4590 .v.pins = (const struct alc_pincfg[]) {
4591 { 0x1a, 0x2101103f }, /* dock line-out */
4592 { 0x1b, 0x23a11040 }, /* dock mic-in */
4593 { }
4594 },
4595 .chained = true,
4596 .chain_id = ALC269_FIXUP_QUANTA_MUTE
4597 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004598};
4599
4600static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Takashi Iwai017f2a12011-07-09 14:42:25 +02004601 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004602 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4603 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4604 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4605 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4606 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004607 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4608 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4609 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4610 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
4611 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
4612 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
Takashi Iwai24519912011-08-16 15:08:49 +02004613 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004614 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4615 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4616 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4617 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4618 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai24519912011-08-16 15:08:49 +02004619 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE),
Takashi Iwai017f2a12011-07-09 14:42:25 +02004620 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02004621 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
4622 {}
4623};
4624
4625
4626static int alc269_fill_coef(struct hda_codec *codec)
4627{
4628 int val;
4629
4630 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
4631 alc_write_coef_idx(codec, 0xf, 0x960b);
4632 alc_write_coef_idx(codec, 0xe, 0x8817);
4633 }
4634
4635 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
4636 alc_write_coef_idx(codec, 0xf, 0x960b);
4637 alc_write_coef_idx(codec, 0xe, 0x8814);
4638 }
4639
4640 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
4641 val = alc_read_coef_idx(codec, 0x04);
4642 /* Power up output pin */
4643 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4644 }
4645
4646 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
4647 val = alc_read_coef_idx(codec, 0xd);
4648 if ((val & 0x0c00) >> 10 != 0x1) {
4649 /* Capless ramp up clock control */
4650 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4651 }
4652 val = alc_read_coef_idx(codec, 0x17);
4653 if ((val & 0x01c0) >> 6 != 0x4) {
4654 /* Class D power on reset */
4655 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4656 }
4657 }
4658
4659 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4660 alc_write_coef_idx(codec, 0xd, val | (1<<14));
4661
4662 val = alc_read_coef_idx(codec, 0x4); /* HP */
4663 alc_write_coef_idx(codec, 0x4, val | (1<<11));
4664
4665 return 0;
4666}
4667
4668/*
4669 */
4670#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4671#include "alc269_quirks.c"
4672#endif
4673
4674static int patch_alc269(struct hda_codec *codec)
4675{
4676 struct alc_spec *spec;
4677 int board_config, coef;
4678 int err;
4679
4680 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4681 if (spec == NULL)
4682 return -ENOMEM;
4683
4684 codec->spec = spec;
4685
4686 spec->mixer_nid = 0x0b;
4687
4688 alc_auto_parse_customize_define(codec);
4689
4690 if (codec->vendor_id == 0x10ec0269) {
4691 spec->codec_variant = ALC269_TYPE_ALC269VA;
4692 coef = alc_read_coef_idx(codec, 0);
4693 if ((coef & 0x00f0) == 0x0010) {
4694 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
4695 spec->cdefine.platform_type == 1) {
4696 alc_codec_rename(codec, "ALC271X");
4697 } else if ((coef & 0xf000) == 0x2000) {
4698 alc_codec_rename(codec, "ALC259");
4699 } else if ((coef & 0xf000) == 0x3000) {
4700 alc_codec_rename(codec, "ALC258");
4701 } else if ((coef & 0xfff0) == 0x3010) {
4702 alc_codec_rename(codec, "ALC277");
4703 } else {
4704 alc_codec_rename(codec, "ALC269VB");
4705 }
4706 spec->codec_variant = ALC269_TYPE_ALC269VB;
4707 } else if ((coef & 0x00f0) == 0x0020) {
4708 if (coef == 0xa023)
4709 alc_codec_rename(codec, "ALC259");
4710 else if (coef == 0x6023)
4711 alc_codec_rename(codec, "ALC281X");
4712 else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4713 codec->bus->pci->subsystem_device == 0x21f3)
4714 alc_codec_rename(codec, "ALC3202");
4715 else
4716 alc_codec_rename(codec, "ALC269VC");
4717 spec->codec_variant = ALC269_TYPE_ALC269VC;
4718 } else
4719 alc_fix_pll_init(codec, 0x20, 0x04, 15);
4720 alc269_fill_coef(codec);
4721 }
4722
4723 board_config = alc_board_config(codec, ALC269_MODEL_LAST,
4724 alc269_models, alc269_cfg_tbl);
4725
4726 if (board_config < 0) {
4727 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4728 codec->chip_name);
4729 board_config = ALC_MODEL_AUTO;
4730 }
4731
4732 if (board_config == ALC_MODEL_AUTO) {
4733 alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
4734 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4735 }
4736
4737 if (board_config == ALC_MODEL_AUTO) {
4738 /* automatic parse from the BIOS config */
4739 err = alc269_parse_auto_config(codec);
4740 if (err < 0) {
4741 alc_free(codec);
4742 return err;
4743 }
4744#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4745 else if (!err) {
4746 printk(KERN_INFO
4747 "hda_codec: Cannot set up configuration "
4748 "from BIOS. Using base mode...\n");
4749 board_config = ALC269_BASIC;
4750 }
4751#endif
4752 }
4753
Takashi Iwai1d045db2011-07-07 18:23:21 +02004754 if (board_config != ALC_MODEL_AUTO)
4755 setup_preset(codec, &alc269_presets[board_config]);
4756
Takashi Iwai60a6a842011-07-27 14:01:24 +02004757 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004758 alc_auto_fill_adc_caps(codec);
4759 alc_rebuild_imux_for_auto_mic(codec);
4760 alc_remove_invalid_adc_nids(codec);
4761 }
4762
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004763 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004764 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004765
4766 if (!spec->no_analog && has_cdefine_beep(codec)) {
4767 err = snd_hda_attach_beep_device(codec, 0x1);
4768 if (err < 0) {
4769 alc_free(codec);
4770 return err;
4771 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004772 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004773 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004774
4775 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4776
4777 spec->vmaster_nid = 0x02;
4778
4779 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02004780#ifdef CONFIG_PM
Takashi Iwai1d045db2011-07-07 18:23:21 +02004781 codec->patch_ops.resume = alc269_resume;
4782#endif
4783 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaibe9bc372011-07-08 16:01:47 +02004784 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004785 spec->shutup = alc269_shutup;
4786
4787 alc_init_jacks(codec);
4788#ifdef CONFIG_SND_HDA_POWER_SAVE
4789 if (!spec->loopback.amplist)
4790 spec->loopback.amplist = alc269_loopbacks;
4791 if (alc269_mic2_for_mute_led(codec))
4792 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
4793#endif
4794
4795 return 0;
4796}
4797
4798/*
4799 * ALC861
4800 */
4801
Takashi Iwai1d045db2011-07-07 18:23:21 +02004802static int alc861_parse_auto_config(struct hda_codec *codec)
4803{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004804 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004805 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4806 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004807}
4808
Takashi Iwai1d045db2011-07-07 18:23:21 +02004809#ifdef CONFIG_SND_HDA_POWER_SAVE
4810static const struct hda_amp_list alc861_loopbacks[] = {
4811 { 0x15, HDA_INPUT, 0 },
4812 { 0x15, HDA_INPUT, 1 },
4813 { 0x15, HDA_INPUT, 2 },
4814 { 0x15, HDA_INPUT, 3 },
4815 { } /* end */
4816};
4817#endif
4818
4819
4820/* Pin config fixes */
4821enum {
4822 PINFIX_FSC_AMILO_PI1505,
4823};
4824
4825static const struct alc_fixup alc861_fixups[] = {
4826 [PINFIX_FSC_AMILO_PI1505] = {
4827 .type = ALC_FIXUP_PINS,
4828 .v.pins = (const struct alc_pincfg[]) {
4829 { 0x0b, 0x0221101f }, /* HP */
4830 { 0x0f, 0x90170310 }, /* speaker */
4831 { }
4832 }
4833 },
4834};
4835
4836static const struct snd_pci_quirk alc861_fixup_tbl[] = {
4837 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
4838 {}
4839};
4840
4841/*
4842 */
4843#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4844#include "alc861_quirks.c"
4845#endif
4846
4847static int patch_alc861(struct hda_codec *codec)
4848{
4849 struct alc_spec *spec;
4850 int board_config;
4851 int err;
4852
4853 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4854 if (spec == NULL)
4855 return -ENOMEM;
4856
4857 codec->spec = spec;
4858
4859 spec->mixer_nid = 0x15;
4860
4861 board_config = alc_board_config(codec, ALC861_MODEL_LAST,
4862 alc861_models, alc861_cfg_tbl);
4863
4864 if (board_config < 0) {
4865 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4866 codec->chip_name);
4867 board_config = ALC_MODEL_AUTO;
4868 }
4869
4870 if (board_config == ALC_MODEL_AUTO) {
4871 alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
4872 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
4873 }
4874
4875 if (board_config == ALC_MODEL_AUTO) {
4876 /* automatic parse from the BIOS config */
4877 err = alc861_parse_auto_config(codec);
4878 if (err < 0) {
4879 alc_free(codec);
4880 return err;
4881 }
4882#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4883 else if (!err) {
4884 printk(KERN_INFO
4885 "hda_codec: Cannot set up configuration "
4886 "from BIOS. Using base mode...\n");
4887 board_config = ALC861_3ST_DIG;
4888 }
4889#endif
4890 }
4891
Takashi Iwai1d045db2011-07-07 18:23:21 +02004892 if (board_config != ALC_MODEL_AUTO)
4893 setup_preset(codec, &alc861_presets[board_config]);
4894
Takashi Iwai60a6a842011-07-27 14:01:24 +02004895 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004896 alc_auto_fill_adc_caps(codec);
4897 alc_rebuild_imux_for_auto_mic(codec);
4898 alc_remove_invalid_adc_nids(codec);
4899 }
4900
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004901 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwai1d045db2011-07-07 18:23:21 +02004902 set_capture_mixer(codec);
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004903
4904 if (!spec->no_analog) {
4905 err = snd_hda_attach_beep_device(codec, 0x23);
4906 if (err < 0) {
4907 alc_free(codec);
4908 return err;
4909 }
4910 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
4911 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02004912
4913 spec->vmaster_nid = 0x03;
4914
4915 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
4916
4917 codec->patch_ops = alc_patch_ops;
4918 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwai72dcd8e2011-07-08 15:16:55 +02004919 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02004920#ifdef CONFIG_SND_HDA_POWER_SAVE
4921 spec->power_hook = alc_power_eapd;
4922#endif
4923 }
4924#ifdef CONFIG_SND_HDA_POWER_SAVE
4925 if (!spec->loopback.amplist)
4926 spec->loopback.amplist = alc861_loopbacks;
4927#endif
4928
4929 return 0;
4930}
4931
4932/*
4933 * ALC861-VD support
4934 *
4935 * Based on ALC882
4936 *
4937 * In addition, an independent DAC
4938 */
4939#ifdef CONFIG_SND_HDA_POWER_SAVE
4940#define alc861vd_loopbacks alc880_loopbacks
4941#endif
4942
Takashi Iwai1d045db2011-07-07 18:23:21 +02004943static int alc861vd_parse_auto_config(struct hda_codec *codec)
4944{
Takashi Iwai1d045db2011-07-07 18:23:21 +02004945 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02004946 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4947 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02004948}
4949
Takashi Iwai1d045db2011-07-07 18:23:21 +02004950enum {
4951 ALC660VD_FIX_ASUS_GPIO1
4952};
4953
4954/* reset GPIO1 */
4955static const struct alc_fixup alc861vd_fixups[] = {
4956 [ALC660VD_FIX_ASUS_GPIO1] = {
4957 .type = ALC_FIXUP_VERBS,
4958 .v.verbs = (const struct hda_verb[]) {
4959 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
4960 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4961 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4962 { }
4963 }
4964 },
4965};
4966
4967static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
4968 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
4969 {}
4970};
4971
4972static const struct hda_verb alc660vd_eapd_verbs[] = {
4973 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
4974 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
4975 { }
4976};
4977
4978/*
4979 */
4980#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
4981#include "alc861vd_quirks.c"
4982#endif
4983
4984static int patch_alc861vd(struct hda_codec *codec)
4985{
4986 struct alc_spec *spec;
4987 int err, board_config;
4988
4989 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4990 if (spec == NULL)
4991 return -ENOMEM;
4992
4993 codec->spec = spec;
4994
4995 spec->mixer_nid = 0x0b;
4996
4997 board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
4998 alc861vd_models, alc861vd_cfg_tbl);
4999
5000 if (board_config < 0) {
5001 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5002 codec->chip_name);
5003 board_config = ALC_MODEL_AUTO;
5004 }
5005
5006 if (board_config == ALC_MODEL_AUTO) {
5007 alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
5008 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
5009 }
5010
5011 if (board_config == ALC_MODEL_AUTO) {
5012 /* automatic parse from the BIOS config */
5013 err = alc861vd_parse_auto_config(codec);
5014 if (err < 0) {
5015 alc_free(codec);
5016 return err;
5017 }
5018#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5019 else if (!err) {
5020 printk(KERN_INFO
5021 "hda_codec: Cannot set up configuration "
5022 "from BIOS. Using base mode...\n");
5023 board_config = ALC861VD_3ST;
5024 }
5025#endif
5026 }
5027
Takashi Iwai1d045db2011-07-07 18:23:21 +02005028 if (board_config != ALC_MODEL_AUTO)
5029 setup_preset(codec, &alc861vd_presets[board_config]);
5030
5031 if (codec->vendor_id == 0x10ec0660) {
5032 /* always turn on EAPD */
5033 add_verb(spec, alc660vd_eapd_verbs);
5034 }
5035
Takashi Iwai60a6a842011-07-27 14:01:24 +02005036 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005037 alc_auto_fill_adc_caps(codec);
5038 alc_rebuild_imux_for_auto_mic(codec);
5039 alc_remove_invalid_adc_nids(codec);
5040 }
5041
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005042 if (!spec->no_analog && !spec->cap_mixer)
5043 set_capture_mixer(codec);
5044
5045 if (!spec->no_analog) {
5046 err = snd_hda_attach_beep_device(codec, 0x23);
5047 if (err < 0) {
5048 alc_free(codec);
5049 return err;
5050 }
5051 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5052 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005053
5054 spec->vmaster_nid = 0x02;
5055
5056 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5057
5058 codec->patch_ops = alc_patch_ops;
5059
5060 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005061 spec->init_hook = alc_auto_init_std;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005062 spec->shutup = alc_eapd_shutup;
5063#ifdef CONFIG_SND_HDA_POWER_SAVE
5064 if (!spec->loopback.amplist)
5065 spec->loopback.amplist = alc861vd_loopbacks;
5066#endif
5067
5068 return 0;
5069}
5070
5071/*
5072 * ALC662 support
5073 *
5074 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5075 * configuration. Each pin widget can choose any input DACs and a mixer.
5076 * Each ADC is connected from a mixer of all inputs. This makes possible
5077 * 6-channel independent captures.
5078 *
5079 * In addition, an independent DAC for the multi-playback (not used in this
5080 * driver yet).
5081 */
5082#ifdef CONFIG_SND_HDA_POWER_SAVE
5083#define alc662_loopbacks alc880_loopbacks
5084#endif
5085
5086/*
5087 * BIOS auto configuration
5088 */
5089
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005090static int alc662_parse_auto_config(struct hda_codec *codec)
5091{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005092 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005093 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5094 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5095 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005096
Kailang Yang6227cdc2010-02-25 08:36:52 +01005097 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
5098 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005099 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005100 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005101 ssids = alc662_ssids;
5102 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005103}
5104
Todd Broch6be79482010-12-07 16:51:05 -08005105static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005106 const struct alc_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005107{
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005108 if (action != ALC_FIXUP_ACT_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005109 return;
Todd Broch6be79482010-12-07 16:51:05 -08005110 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5111 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5112 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5113 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5114 (0 << AC_AMPCAP_MUTE_SHIFT)))
5115 printk(KERN_WARNING
5116 "hda_codec: failed to override amp caps for NID 0x2\n");
5117}
5118
David Henningsson6cb3b702010-09-09 08:51:44 +02005119enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005120 ALC662_FIXUP_ASPIRE,
David Henningsson6cb3b702010-09-09 08:51:44 +02005121 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005122 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005123 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005124 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005125 ALC662_FIXUP_HP_RP5800,
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005126 ALC662_FIXUP_ECS,
David Henningsson6cb3b702010-09-09 08:51:44 +02005127};
5128
5129static const struct alc_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005130 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005131 .type = ALC_FIXUP_PINS,
5132 .v.pins = (const struct alc_pincfg[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005133 { 0x15, 0x99130112 }, /* subwoofer */
5134 { }
5135 }
5136 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005137 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005138 .type = ALC_FIXUP_PINS,
5139 .v.pins = (const struct alc_pincfg[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005140 { 0x17, 0x99130112 }, /* subwoofer */
5141 { }
5142 }
5143 },
Todd Broch6be79482010-12-07 16:51:05 -08005144 [ALC272_FIXUP_MARIO] = {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005145 .type = ALC_FIXUP_FUNC,
5146 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005147 },
5148 [ALC662_FIXUP_CZC_P10T] = {
5149 .type = ALC_FIXUP_VERBS,
5150 .v.verbs = (const struct hda_verb[]) {
5151 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5152 {}
5153 }
5154 },
David Henningsson94024cd2011-04-29 14:10:55 +02005155 [ALC662_FIXUP_SKU_IGNORE] = {
5156 .type = ALC_FIXUP_SKU,
5157 .v.sku = ALC_FIXUP_SKU_IGNORE,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005158 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005159 [ALC662_FIXUP_HP_RP5800] = {
5160 .type = ALC_FIXUP_PINS,
5161 .v.pins = (const struct alc_pincfg[]) {
5162 { 0x14, 0x0221201f }, /* HP out */
5163 { }
5164 },
5165 .chained = true,
5166 .chain_id = ALC662_FIXUP_SKU_IGNORE
5167 },
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005168 [ALC662_FIXUP_ECS] = {
5169 .type = ALC_FIXUP_PINS,
5170 .v.pins = (const struct alc_pincfg[]) {
5171 { 0x14, 0x99130110 }, /* speaker */
5172 { 0x18, 0x01a19820 }, /* mic */
5173 { 0x19, 0x99a3092f }, /* int-mic */
5174 { 0x1b, 0x0121401f }, /* HP out */
5175 { }
5176 },
5177 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005178};
5179
Takashi Iwaia9111322011-05-02 11:30:18 +02005180static const struct snd_pci_quirk alc662_fixup_tbl[] = {
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005181 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ECS),
David Henningssona6c47a82011-02-10 15:39:19 +01005182 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02005183 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Daniel T Chen2df03512010-10-10 22:39:28 -04005184 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005185 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005186 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ECS),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05005187 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06005188 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02005189 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
Anisse Astierd2ebd472011-01-20 12:36:21 +01005190 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
David Henningsson6cb3b702010-09-09 08:51:44 +02005191 {}
5192};
5193
Todd Broch6be79482010-12-07 16:51:05 -08005194static const struct alc_model_fixup alc662_fixup_models[] = {
5195 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
5196 {}
5197};
David Henningsson6cb3b702010-09-09 08:51:44 +02005198
5199
Takashi Iwai1d045db2011-07-07 18:23:21 +02005200/*
5201 */
5202#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5203#include "alc662_quirks.c"
5204#endif
5205
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005206static int patch_alc662(struct hda_codec *codec)
5207{
5208 struct alc_spec *spec;
5209 int err, board_config;
Kailang Yang693194f2010-10-21 08:51:48 +02005210 int coef;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005211
5212 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5213 if (!spec)
5214 return -ENOMEM;
5215
5216 codec->spec = spec;
5217
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005218 spec->mixer_nid = 0x0b;
5219
Kailang Yangda00c242010-03-19 11:23:45 +01005220 alc_auto_parse_customize_define(codec);
5221
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02005222 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5223
Kailang Yang693194f2010-10-21 08:51:48 +02005224 coef = alc_read_coef_idx(codec, 0);
5225 if (coef == 0x8020 || coef == 0x8011)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005226 alc_codec_rename(codec, "ALC661");
Kailang Yang693194f2010-10-21 08:51:48 +02005227 else if (coef & (1 << 14) &&
5228 codec->bus->pci->subsystem_vendor == 0x1025 &&
5229 spec->cdefine.platform_type == 1)
Kailang Yangc027ddc2010-03-19 11:33:06 +01005230 alc_codec_rename(codec, "ALC272X");
Kailang Yang693194f2010-10-21 08:51:48 +02005231 else if (coef == 0x4011)
5232 alc_codec_rename(codec, "ALC656");
Kailang Yang274693f2009-12-03 10:07:50 +01005233
Takashi Iwai1d045db2011-07-07 18:23:21 +02005234 board_config = alc_board_config(codec, ALC662_MODEL_LAST,
5235 alc662_models, alc662_cfg_tbl);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005236 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005237 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5238 codec->chip_name);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005239 board_config = ALC_MODEL_AUTO;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005240 }
5241
Takashi Iwai1d045db2011-07-07 18:23:21 +02005242 if (board_config == ALC_MODEL_AUTO) {
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005243 alc_pick_fixup(codec, alc662_fixup_models,
5244 alc662_fixup_tbl, alc662_fixups);
5245 alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005246 /* automatic parse from the BIOS config */
5247 err = alc662_parse_auto_config(codec);
5248 if (err < 0) {
5249 alc_free(codec);
5250 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005251 }
5252#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
5253 else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005254 printk(KERN_INFO
5255 "hda_codec: Cannot set up configuration "
5256 "from BIOS. Using base mode...\n");
5257 board_config = ALC662_3ST_2ch_DIG;
5258 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005259#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005260 }
5261
Takashi Iwai1d045db2011-07-07 18:23:21 +02005262 if (board_config != ALC_MODEL_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005263 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005264
Takashi Iwai60a6a842011-07-27 14:01:24 +02005265 if (!spec->no_analog && !spec->adc_nids) {
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005266 alc_auto_fill_adc_caps(codec);
Takashi Iwai21268962011-07-07 15:01:13 +02005267 alc_rebuild_imux_for_auto_mic(codec);
Takashi Iwaid6cc9fab2011-07-06 16:38:42 +02005268 alc_remove_invalid_adc_nids(codec);
Takashi Iwaidd704692009-08-11 08:45:11 +02005269 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005270
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005271 if (!spec->no_analog && !spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005272 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005273
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005274 if (!spec->no_analog && has_cdefine_beep(codec)) {
5275 err = snd_hda_attach_beep_device(codec, 0x1);
5276 if (err < 0) {
5277 alc_free(codec);
5278 return err;
5279 }
Kailang Yangda00c242010-03-19 11:23:45 +01005280 switch (codec->vendor_id) {
5281 case 0x10ec0662:
5282 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5283 break;
5284 case 0x10ec0272:
5285 case 0x10ec0663:
5286 case 0x10ec0665:
5287 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5288 break;
5289 case 0x10ec0273:
5290 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5291 break;
5292 }
Kailang Yangcec27c82010-02-04 14:18:18 +01005293 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01005294 spec->vmaster_nid = 0x02;
5295
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005296 alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
5297
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005298 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005299 if (board_config == ALC_MODEL_AUTO)
Takashi Iwaie4770622011-07-08 11:11:35 +02005300 spec->init_hook = alc_auto_init_std;
Takashi Iwai1c716152011-04-07 10:37:16 +02005301 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02005302
Kailang Yangbf1b0222010-10-21 08:49:56 +02005303 alc_init_jacks(codec);
5304
Takashi Iwaicb53c622007-08-10 17:21:45 +02005305#ifdef CONFIG_SND_HDA_POWER_SAVE
5306 if (!spec->loopback.amplist)
5307 spec->loopback.amplist = alc662_loopbacks;
5308#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005309
5310 return 0;
5311}
5312
Kailang Yang274693f2009-12-03 10:07:50 +01005313static int patch_alc888(struct hda_codec *codec)
5314{
5315 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
5316 kfree(codec->chip_name);
Kailang Yang01e0f132010-11-22 10:59:36 +01005317 if (codec->vendor_id == 0x10ec0887)
5318 codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
5319 else
5320 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005321 if (!codec->chip_name) {
5322 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005323 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005324 }
5325 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005326 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +01005327 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +01005328}
5329
Kailang Yangb478b992011-05-18 11:51:15 +02005330static int patch_alc899(struct hda_codec *codec)
5331{
5332 if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
5333 kfree(codec->chip_name);
5334 codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
5335 }
5336 return patch_alc882(codec);
5337}
5338
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005339/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005340 * ALC680 support
5341 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005342
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005343static int alc680_parse_auto_config(struct hda_codec *codec)
5344{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005345 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005346}
5347
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005348/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005349 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005350static int patch_alc680(struct hda_codec *codec)
5351{
5352 struct alc_spec *spec;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005353 int err;
5354
5355 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5356 if (spec == NULL)
5357 return -ENOMEM;
5358
5359 codec->spec = spec;
5360
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02005361 /* ALC680 has no aa-loopback mixer */
5362
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02005363 /* automatic parse from the BIOS config */
5364 err = alc680_parse_auto_config(codec);
5365 if (err < 0) {
5366 alc_free(codec);
5367 return err;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005368 }
5369
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005370 if (!spec->no_analog && !spec->cap_mixer)
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005371 set_capture_mixer(codec);
5372
5373 spec->vmaster_nid = 0x02;
5374
5375 codec->patch_ops = alc_patch_ops;
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02005376 spec->init_hook = alc_auto_init_std;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005377
5378 return 0;
5379}
5380
5381/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382 * patch entries
5383 */
Takashi Iwaia9111322011-05-02 11:30:18 +02005384static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02005385 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005387 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005388 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02005389 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01005390 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005391 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02005392 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01005393 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02005394 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005395 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005396 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005397 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5398 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5399 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005400 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +02005401 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005402 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5403 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02005404 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01005405 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01005406 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02005407 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01005408 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +02005410 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02005411 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005412 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02005413 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +02005414 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005415 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Kailang Yang01e0f132010-11-22 10:59:36 +01005416 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
Kailang Yang44426082008-10-15 11:18:05 +02005417 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +02005418 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005419 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai49535502009-06-30 15:28:30 +02005420 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01005421 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Kailang Yangb478b992011-05-18 11:51:15 +02005422 { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423 {} /* terminator */
5424};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01005425
5426MODULE_ALIAS("snd-hda-codec-id:10ec*");
5427
5428MODULE_LICENSE("GPL");
5429MODULE_DESCRIPTION("Realtek HD-audio codec");
5430
5431static struct hda_codec_preset_list realtek_list = {
5432 .preset = snd_hda_preset_realtek,
5433 .owner = THIS_MODULE,
5434};
5435
5436static int __init patch_realtek_init(void)
5437{
5438 return snd_hda_add_codec_preset(&realtek_list);
5439}
5440
5441static void __exit patch_realtek_exit(void)
5442{
5443 snd_hda_delete_codec_preset(&realtek_list);
5444}
5445
5446module_init(patch_realtek_init)
5447module_exit(patch_realtek_exit)