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