blob: 8d60b1f25ce194987a7e648a7089be3960863c82 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * HD audio interface patch for ALC 260/880/882 codecs
5 *
Kailang Yangdf694da2005-12-05 19:42:22 +01006 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Takashi Iwai <tiwai@suse.de>
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01009 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <sound/core.h>
31#include "hda_codec.h"
32#include "hda_local.h"
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090033#include "hda_beep.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Kailang Yangccc656c2006-10-17 12:32:26 +020035#define ALC880_FRONT_EVENT 0x01
36#define ALC880_DCVOL_EVENT 0x02
37#define ALC880_HP_EVENT 0x04
38#define ALC880_MIC_EVENT 0x08
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40/* ALC880 board config type */
41enum {
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 ALC880_3ST,
43 ALC880_3ST_DIG,
44 ALC880_5ST,
45 ALC880_5ST_DIG,
46 ALC880_W810,
Takashi Iwaidfc0ff62005-05-12 14:31:49 +020047 ALC880_Z71V,
Takashi Iwaib6482d42005-06-27 15:32:43 +020048 ALC880_6ST,
Takashi Iwai16ded522005-06-10 19:58:24 +020049 ALC880_6ST_DIG,
50 ALC880_F1734,
51 ALC880_ASUS,
52 ALC880_ASUS_DIG,
53 ALC880_ASUS_W1V,
Kailang Yangdf694da2005-12-05 19:42:22 +010054 ALC880_ASUS_DIG2,
Tobin Davis2cf9f0f2007-02-07 16:04:25 +010055 ALC880_FUJITSU,
Takashi Iwai16ded522005-06-10 19:58:24 +020056 ALC880_UNIWILL_DIG,
Kailang Yangccc656c2006-10-17 12:32:26 +020057 ALC880_UNIWILL,
58 ALC880_UNIWILL_P53,
Kailang Yangdf694da2005-12-05 19:42:22 +010059 ALC880_CLEVO,
60 ALC880_TCL_S700,
Takashi Iwaiae6b8132006-03-03 16:47:17 +010061 ALC880_LG,
Takashi Iwaid6815182006-03-23 16:06:23 +010062 ALC880_LG_LW,
Takashi Iwaidf99cd32008-04-25 15:25:04 +020063 ALC880_MEDION_RIM,
Takashi Iwaie9edcee2005-06-13 14:16:38 +020064#ifdef CONFIG_SND_DEBUG
65 ALC880_TEST,
66#endif
Kailang Yangdf694da2005-12-05 19:42:22 +010067 ALC880_AUTO,
Takashi Iwai16ded522005-06-10 19:58:24 +020068 ALC880_MODEL_LAST /* last tag */
69};
70
71/* ALC260 models */
72enum {
73 ALC260_BASIC,
74 ALC260_HP,
Kailang Yang3f878302008-08-26 13:02:23 +020075 ALC260_HP_DC7600,
Kailang Yangdf694da2005-12-05 19:42:22 +010076 ALC260_HP_3013,
77 ALC260_FUJITSU_S702X,
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +010078 ALC260_ACER,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020079 ALC260_WILL,
80 ALC260_REPLACER_672V,
Michael Schwingencc959482009-02-22 18:58:45 +010081 ALC260_FAVORIT100,
Jonathan Woithe7cf51e482006-02-09 12:01:26 +010082#ifdef CONFIG_SND_DEBUG
83 ALC260_TEST,
84#endif
Kailang Yangdf694da2005-12-05 19:42:22 +010085 ALC260_AUTO,
Takashi Iwai16ded522005-06-10 19:58:24 +020086 ALC260_MODEL_LAST /* last tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087};
88
Kailang Yangdf694da2005-12-05 19:42:22 +010089/* ALC262 models */
90enum {
91 ALC262_BASIC,
Kailang Yangccc656c2006-10-17 12:32:26 +020092 ALC262_HIPPO,
93 ALC262_HIPPO_1,
Takashi Iwai834be882006-03-01 14:16:17 +010094 ALC262_FUJITSU,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020095 ALC262_HP_BPC,
Kailang Yangcd7509a2007-01-26 18:33:17 +010096 ALC262_HP_BPC_D7000_WL,
97 ALC262_HP_BPC_D7000_WF,
Kailang Yang66d2a9d2007-11-14 12:06:21 +010098 ALC262_HP_TC_T5735,
Kailang Yang8c427222008-01-10 13:03:59 +010099 ALC262_HP_RP5700,
Takashi Iwai304dcaa2006-07-25 14:51:16 +0200100 ALC262_BENQ_ED8,
Kailang Yang272a5272007-05-14 11:00:38 +0200101 ALC262_SONY_ASSAMD,
Kailang Yang83c34212007-07-05 11:43:05 +0200102 ALC262_BENQ_T31,
Tobin Davisf651b502007-10-26 12:40:47 +0200103 ALC262_ULTRA,
Jiang zhe0e31daf2008-03-20 12:12:39 +0100104 ALC262_LENOVO_3000,
Pascal Terjane8f9ae22008-08-04 14:36:05 +0200105 ALC262_NEC,
Kailang Yang4e555fe2008-08-26 13:05:55 +0200106 ALC262_TOSHIBA_S06,
Hiroshi Miura9f99a632008-08-28 16:09:06 +0200107 ALC262_TOSHIBA_RX1,
Tony Vroonba340e82009-02-02 19:01:30 +0000108 ALC262_TYAN,
Kailang Yangdf694da2005-12-05 19:42:22 +0100109 ALC262_AUTO,
110 ALC262_MODEL_LAST /* last tag */
111};
112
Kailang Yanga361d842007-06-05 12:30:55 +0200113/* ALC268 models */
114enum {
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +0200115 ALC267_QUANTA_IL1,
Kailang Yanga361d842007-06-05 12:30:55 +0200116 ALC268_3ST,
Kailang Yangd1a991a2007-08-15 16:21:59 +0200117 ALC268_TOSHIBA,
Takashi Iwaid2738092007-08-16 14:59:45 +0200118 ALC268_ACER,
Takashi Iwaic238b4f2008-11-05 14:57:20 +0100119 ALC268_ACER_DMIC,
Kailang Yang8ef355d2008-08-26 13:10:22 +0200120 ALC268_ACER_ASPIRE_ONE,
Takashi Iwai3866f0b2008-01-15 12:37:42 +0100121 ALC268_DELL,
Mirco Tischlerf12462c2008-02-04 12:33:59 +0100122 ALC268_ZEPTO,
Jonathan Woithe86c53bd2008-01-08 12:33:19 +0100123#ifdef CONFIG_SND_DEBUG
124 ALC268_TEST,
125#endif
Kailang Yanga361d842007-06-05 12:30:55 +0200126 ALC268_AUTO,
127 ALC268_MODEL_LAST /* last tag */
128};
129
Kailang Yangf6a92242007-12-13 16:52:54 +0100130/* ALC269 models */
131enum {
132 ALC269_BASIC,
Kailang Yang60db6b52008-08-26 13:13:00 +0200133 ALC269_QUANTA_FL1,
Kailang Yang84898e82010-02-04 14:16:14 +0100134 ALC269_AMIC,
135 ALC269_DMIC,
136 ALC269VB_AMIC,
137 ALC269VB_DMIC,
Takashi Iwai26f5df22008-11-03 17:39:46 +0100138 ALC269_FUJITSU,
Tony Vroon64154832008-11-06 15:08:49 +0000139 ALC269_LIFEBOOK,
Kailang Yangf6a92242007-12-13 16:52:54 +0100140 ALC269_AUTO,
141 ALC269_MODEL_LAST /* last tag */
142};
143
Kailang Yangdf694da2005-12-05 19:42:22 +0100144/* ALC861 models */
145enum {
146 ALC861_3ST,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200147 ALC660_3ST,
Kailang Yangdf694da2005-12-05 19:42:22 +0100148 ALC861_3ST_DIG,
149 ALC861_6ST_DIG,
Takashi Iwai22309c32006-08-09 16:57:28 +0200150 ALC861_UNIWILL_M31,
Tobin Davisa53d1ae2006-10-17 12:00:28 +0200151 ALC861_TOSHIBA,
Mariusz Domanski7cdbff92006-10-23 13:42:56 +0200152 ALC861_ASUS,
Takashi Iwai56bb0ca2006-11-22 11:52:52 +0100153 ALC861_ASUS_LAPTOP,
Kailang Yangdf694da2005-12-05 19:42:22 +0100154 ALC861_AUTO,
155 ALC861_MODEL_LAST,
156};
157
Jakub Schmidtkef32610e2007-02-02 18:17:27 +0100158/* ALC861-VD models */
159enum {
160 ALC660VD_3ST,
Mike Crash6963f842007-06-25 12:12:51 +0200161 ALC660VD_3ST_DIG,
Takashi Iwai13c94742008-11-05 08:06:08 +0100162 ALC660VD_ASUS_V1S,
Jakub Schmidtkef32610e2007-02-02 18:17:27 +0100163 ALC861VD_3ST,
164 ALC861VD_3ST_DIG,
165 ALC861VD_6ST_DIG,
Kailang Yangbdd148a2007-05-08 15:19:08 +0200166 ALC861VD_LENOVO,
Kailang Yang272a5272007-05-14 11:00:38 +0200167 ALC861VD_DALLAS,
Kailang Yangd1a991a2007-08-15 16:21:59 +0200168 ALC861VD_HP,
Jakub Schmidtkef32610e2007-02-02 18:17:27 +0100169 ALC861VD_AUTO,
170 ALC861VD_MODEL_LAST,
171};
172
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200173/* ALC662 models */
174enum {
175 ALC662_3ST_2ch_DIG,
176 ALC662_3ST_6ch_DIG,
177 ALC662_3ST_6ch,
178 ALC662_5ST_DIG,
179 ALC662_LENOVO_101E,
Kailang Yang291702f2007-10-16 14:28:03 +0200180 ALC662_ASUS_EEEPC_P701,
Kailang Yang8c427222008-01-10 13:03:59 +0100181 ALC662_ASUS_EEEPC_EP20,
Kailang Yang6dda9f42008-05-27 12:05:31 +0200182 ALC663_ASUS_M51VA,
183 ALC663_ASUS_G71V,
184 ALC663_ASUS_H13,
185 ALC663_ASUS_G50V,
Kailang Yangf1d4e282008-08-26 14:03:29 +0200186 ALC662_ECS,
187 ALC663_ASUS_MODE1,
188 ALC662_ASUS_MODE2,
189 ALC663_ASUS_MODE3,
190 ALC663_ASUS_MODE4,
191 ALC663_ASUS_MODE5,
192 ALC663_ASUS_MODE6,
Kailang Yangebb83ee2009-12-17 12:23:00 +0100193 ALC663_ASUS_MODE7,
194 ALC663_ASUS_MODE8,
Kailang Yang622e84c2009-04-21 07:39:04 +0200195 ALC272_DELL,
196 ALC272_DELL_ZM1,
Chris Pockelé9541ba12009-05-12 08:08:53 +0200197 ALC272_SAMSUNG_NC10,
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200198 ALC662_AUTO,
199 ALC662_MODEL_LAST,
200};
201
Kailang Yangdf694da2005-12-05 19:42:22 +0100202/* ALC882 models */
203enum {
204 ALC882_3ST_DIG,
205 ALC882_6ST_DIG,
Takashi Iwai4b146cb2006-07-28 14:42:36 +0200206 ALC882_ARIMA,
Kailang Yangbdd148a2007-05-08 15:19:08 +0200207 ALC882_W2JC,
Kailang Yang272a5272007-05-14 11:00:38 +0200208 ALC882_TARGA,
209 ALC882_ASUS_A7J,
Takashi Iwai914759b2007-09-06 14:52:04 +0200210 ALC882_ASUS_A7M,
Tobin Davis9102cd12006-12-15 10:02:12 +0100211 ALC885_MACPRO,
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -0800212 ALC885_MBA21,
Takashi Iwai87350ad2007-08-16 18:19:38 +0200213 ALC885_MBP3,
Kacper Szczesniak41d55452009-05-07 12:47:43 +0200214 ALC885_MB5,
Luke Yelaviche458b1f2010-02-12 16:28:29 +1100215 ALC885_MACMINI3,
Nicola Fagnanic54728d2007-07-19 23:28:52 +0200216 ALC885_IMAC24,
Justin P. Mattock4b7e1802009-12-07 15:07:46 -0800217 ALC885_IMAC91,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200218 ALC883_3ST_2ch_DIG,
219 ALC883_3ST_6ch_DIG,
220 ALC883_3ST_6ch,
221 ALC883_6ST_DIG,
Kailang Yangccc656c2006-10-17 12:32:26 +0200222 ALC883_TARGA_DIG,
223 ALC883_TARGA_2ch_DIG,
David Heidelberger64a8be72009-06-08 16:15:18 +0200224 ALC883_TARGA_8ch_DIG,
Vladimir Avdoninbab282b92006-08-22 13:31:58 +0200225 ALC883_ACER,
Tobin Davis2880a862007-08-07 11:50:26 +0200226 ALC883_ACER_ASPIRE,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +0800227 ALC888_ACER_ASPIRE_4930G,
Tony Vroond2fd4b02009-06-21 00:40:10 +0100228 ALC888_ACER_ASPIRE_6530G,
Hector Martin3b315d72009-06-02 10:54:19 +0200229 ALC888_ACER_ASPIRE_8930G,
Denis Kuplyakovfc86f952009-08-25 18:15:59 +0200230 ALC888_ACER_ASPIRE_7730G,
Tobin Davisc07584c2006-10-13 12:32:16 +0200231 ALC883_MEDION,
Kailang Yangea1fb292008-08-26 12:58:38 +0200232 ALC883_MEDION_MD2,
Maurus Cuelenaere7ad7b212010-04-06 18:12:52 +0200233 ALC883_MEDION_WIM2160,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +0100234 ALC883_LAPTOP_EAPD,
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200235 ALC883_LENOVO_101E_2ch,
Kailang Yang272a5272007-05-14 11:00:38 +0200236 ALC883_LENOVO_NB0763,
Kailang Yang189609a2007-08-20 11:31:23 +0200237 ALC888_LENOVO_MS7195_DIG,
Kailang Yange2757d52008-08-26 13:17:46 +0200238 ALC888_LENOVO_SKY,
Kailang Yangea1fb292008-08-26 12:58:38 +0200239 ALC883_HAIER_W66,
Claudio Matsuoka4723c022007-07-13 14:36:19 +0200240 ALC888_3ST_HP,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +0100241 ALC888_6ST_DELL,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +0100242 ALC883_MITAC,
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -0430243 ALC883_CLEVO_M540R,
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +0100244 ALC883_CLEVO_M720,
Jiang zhefb97dc62008-03-06 11:07:11 +0100245 ALC883_FUJITSU_PI2515,
Vincent Petryef8ef5f2008-11-23 11:31:41 +0800246 ALC888_FUJITSU_XA3530,
Jiang zhe17bba1b2008-06-04 12:11:07 +0200247 ALC883_3ST_6ch_INTEL,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200248 ALC889A_INTEL,
249 ALC889_INTEL,
Kailang Yange2757d52008-08-26 13:17:46 +0200250 ALC888_ASUS_M90V,
251 ALC888_ASUS_EEE1601,
Torben Schulzeb4c41d2009-05-18 15:02:35 +0200252 ALC889A_MB31,
Wu Fengguang3ab90932008-11-17 09:51:09 +0100253 ALC1200_ASUS_P5Q,
Guido Günther3e1647c2009-06-05 00:47:26 +0200254 ALC883_SONY_VAIO_TT,
Takashi Iwai4953550a2009-06-30 15:28:30 +0200255 ALC882_AUTO,
256 ALC882_MODEL_LAST,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200257};
258
Kailang Yangdf694da2005-12-05 19:42:22 +0100259/* for GPIO Poll */
260#define GPIO_MASK 0x03
261
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200262/* extra amp-initialization sequence types */
263enum {
264 ALC_INIT_NONE,
265 ALC_INIT_DEFAULT,
266 ALC_INIT_GPIO1,
267 ALC_INIT_GPIO2,
268 ALC_INIT_GPIO3,
269};
270
Takashi Iwai6c819492009-08-10 18:47:44 +0200271struct alc_mic_route {
272 hda_nid_t pin;
273 unsigned char mux_idx;
274 unsigned char amix_idx;
275};
276
277#define MUX_IDX_UNDEF ((unsigned char)-1)
278
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279struct alc_spec {
280 /* codec parameterization */
Kailang Yangdf694da2005-12-05 19:42:22 +0100281 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 unsigned int num_mixers;
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100283 struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100284 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Takashi Iwai2d9c6482009-10-13 08:06:55 +0200286 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200287 * don't forget NULL
288 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200289 */
290 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200292 char stream_name_analog[32]; /* analog PCM stream */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 struct hda_pcm_stream *stream_analog_playback;
294 struct hda_pcm_stream *stream_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +0100295 struct hda_pcm_stream *stream_analog_alt_playback;
296 struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200298 char stream_name_digital[32]; /* digital PCM stream */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 struct hda_pcm_stream *stream_digital_playback;
300 struct hda_pcm_stream *stream_digital_capture;
301
302 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200303 struct hda_multi_out multiout; /* playback set-up
304 * max_channels, dacs must be set
305 * dig_out_nid and hp_nid are optional
306 */
Takashi Iwai63300792008-01-24 15:31:36 +0100307 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100308 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100309 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
311 /* capture */
312 unsigned int num_adc_nids;
313 hda_nid_t *adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100314 hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200315 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
317 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200318 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 const struct hda_input_mux *input_mux;
320 unsigned int cur_mux[3];
Takashi Iwai6c819492009-08-10 18:47:44 +0200321 struct alc_mic_route ext_mic;
322 struct alc_mic_route int_mic;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
324 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100325 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200327 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200328 int const_channel_count;
329 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330
331 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100332 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200333
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200334 /* dynamic controls, init_verbs and input_mux */
335 struct auto_pin_cfg autocfg;
Takashi Iwai603c4012008-07-30 15:01:44 +0200336 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200337 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200338 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai4953550a2009-06-30 15:28:30 +0200339 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
340 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai834be882006-03-01 14:16:17 +0100341
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100342 /* hooks */
343 void (*init_hook)(struct hda_codec *codec);
344 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100345#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500346 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100347#endif
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100348
Takashi Iwai834be882006-03-01 14:16:17 +0100349 /* for pin sensing */
350 unsigned int sense_updated: 1;
351 unsigned int jack_present: 1;
Takashi Iwaibec15c32008-01-28 18:16:30 +0100352 unsigned int master_sw: 1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200353 unsigned int auto_mic:1;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200354
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100355 /* other flags */
356 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200357 int init_amp;
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100358
Takashi Iwai2134ea42008-01-10 16:53:55 +0100359 /* for virtual master */
360 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200361#ifdef CONFIG_SND_HDA_POWER_SAVE
362 struct hda_loopback_check loopback;
363#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200364
365 /* for PLL fix */
366 hda_nid_t pll_nid;
367 unsigned int pll_coef_idx, pll_coef_bit;
Kailang Yangdf694da2005-12-05 19:42:22 +0100368};
369
370/*
371 * configuration template - to be copied to the spec instance
372 */
373struct alc_config_preset {
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200374 struct snd_kcontrol_new *mixers[5]; /* should be identical size
375 * with spec
376 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100377 struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Kailang Yangdf694da2005-12-05 19:42:22 +0100378 const struct hda_verb *init_verbs[5];
379 unsigned int num_dacs;
380 hda_nid_t *dac_nids;
381 hda_nid_t dig_out_nid; /* optional */
382 hda_nid_t hp_nid; /* optional */
Wu Fengguangb25c9da2009-02-06 15:02:27 +0800383 hda_nid_t *slave_dig_outs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100384 unsigned int num_adc_nids;
385 hda_nid_t *adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100386 hda_nid_t *capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +0100387 hda_nid_t dig_in_nid;
388 unsigned int num_channel_mode;
389 const struct hda_channel_mode *channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200390 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200391 int const_channel_count;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200392 unsigned int num_mux_defs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100393 const struct hda_input_mux *input_mux;
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100394 void (*unsol_event)(struct hda_codec *, unsigned int);
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200395 void (*setup)(struct hda_codec *);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100396 void (*init_hook)(struct hda_codec *);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200397#ifdef CONFIG_SND_HDA_POWER_SAVE
398 struct hda_amp_list *loopbacks;
Daniel T Chenc97259d2009-12-27 18:52:08 -0500399 void (*power_hook)(struct hda_codec *codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200400#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401};
402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404/*
405 * input MUX handling
406 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200407static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
408 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409{
410 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
411 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200412 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
413 if (mux_idx >= spec->num_mux_defs)
414 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100415 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
416 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200417 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418}
419
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200420static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
421 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422{
423 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
424 struct alc_spec *spec = codec->spec;
425 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
426
427 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
428 return 0;
429}
430
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200431static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
432 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
434 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
435 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100436 const struct hda_input_mux *imux;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaicd896c32008-11-18 12:36:33 +0100438 unsigned int mux_idx;
Takashi Iwaie1406342008-02-11 18:32:32 +0100439 hda_nid_t nid = spec->capsrc_nids ?
440 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200441 unsigned int type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Takashi Iwaicd896c32008-11-18 12:36:33 +0100443 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
444 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100445 if (!imux->num_items && mux_idx > 0)
446 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100447
Takashi Iwaia22d5432009-07-27 12:54:26 +0200448 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200449 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100450 /* Matrix-mixer style (e.g. ALC882) */
451 unsigned int *cur_val = &spec->cur_mux[adc_idx];
452 unsigned int i, idx;
453
454 idx = ucontrol->value.enumerated.item[0];
455 if (idx >= imux->num_items)
456 idx = imux->num_items - 1;
457 if (*cur_val == idx)
458 return 0;
459 for (i = 0; i < imux->num_items; i++) {
460 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
461 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
462 imux->items[i].index,
463 HDA_AMP_MUTE, v);
464 }
465 *cur_val = idx;
466 return 1;
467 } else {
468 /* MUX style (e.g. ALC880) */
Takashi Iwaicd896c32008-11-18 12:36:33 +0100469 return snd_hda_input_mux_put(codec, imux, ucontrol, nid,
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100470 &spec->cur_mux[adc_idx]);
471 }
472}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474/*
475 * channel mode setting
476 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200477static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
478 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
480 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
481 struct alc_spec *spec = codec->spec;
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100482 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
483 spec->num_channel_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}
485
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200486static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
487 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
489 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
490 struct alc_spec *spec = codec->spec;
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100491 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200492 spec->num_channel_mode,
Hector Martin3b315d72009-06-02 10:54:19 +0200493 spec->ext_channel_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200496static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
497 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498{
499 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
500 struct alc_spec *spec = codec->spec;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200501 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
502 spec->num_channel_mode,
Hector Martin3b315d72009-06-02 10:54:19 +0200503 &spec->ext_channel_count);
504 if (err >= 0 && !spec->const_channel_count) {
505 spec->multiout.max_channels = spec->ext_channel_count;
506 if (spec->need_dac_fix)
507 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
508 }
Takashi Iwai4e195a72006-07-28 14:47:34 +0200509 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510}
511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512/*
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100513 * Control the mode of pin widget settings via the mixer. "pc" is used
Kailang Yangea1fb292008-08-26 12:58:38 +0200514 * instead of "%" to avoid consequences of accidently treating the % as
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100515 * being part of a format specifier. Maximum allowed length of a value is
516 * 63 characters plus NULL terminator.
Jonathan Woithe7cf51e482006-02-09 12:01:26 +0100517 *
518 * Note: some retasking pin complexes seem to ignore requests for input
519 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
520 * are requested. Therefore order this list so that this behaviour will not
521 * cause problems when mixer clients move through the enum sequentially.
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200522 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
523 * March 2006.
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200524 */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100525static char *alc_pin_mode_names[] = {
Jonathan Woithe7cf51e482006-02-09 12:01:26 +0100526 "Mic 50pc bias", "Mic 80pc bias",
527 "Line in", "Line out", "Headphone out",
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100528};
529static unsigned char alc_pin_mode_values[] = {
Jonathan Woithe7cf51e482006-02-09 12:01:26 +0100530 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100531};
532/* The control can present all 5 options, or it can limit the options based
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200533 * in the pin being assumed to be exclusively an input or an output pin. In
534 * addition, "input" pins may or may not process the mic bias option
535 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
536 * accept requests for bias as of chip versions up to March 2006) and/or
537 * wiring in the computer.
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100538 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200539#define ALC_PIN_DIR_IN 0x00
540#define ALC_PIN_DIR_OUT 0x01
541#define ALC_PIN_DIR_INOUT 0x02
542#define ALC_PIN_DIR_IN_NOMICBIAS 0x03
543#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100544
Kailang Yangea1fb292008-08-26 12:58:38 +0200545/* Info about the pin modes supported by the different pin direction modes.
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100546 * For each direction the minimum and maximum values are given.
547 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200548static signed char alc_pin_mode_dir_info[5][2] = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100549 { 0, 2 }, /* ALC_PIN_DIR_IN */
550 { 3, 4 }, /* ALC_PIN_DIR_OUT */
551 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200552 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
553 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100554};
555#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
556#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
557#define alc_pin_mode_n_items(_dir) \
558 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
559
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200560static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
561 struct snd_ctl_elem_info *uinfo)
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200562{
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100563 unsigned int item_num = uinfo->value.enumerated.item;
564 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
565
566 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200567 uinfo->count = 1;
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100568 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
569
570 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
571 item_num = alc_pin_mode_min(dir);
572 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200573 return 0;
574}
575
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200576static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
577 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200578{
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100579 unsigned int i;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200580 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
581 hda_nid_t nid = kcontrol->private_value & 0xffff;
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100582 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200583 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200584 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
585 AC_VERB_GET_PIN_WIDGET_CONTROL,
586 0x00);
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200587
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100588 /* Find enumerated value for current pinctl setting */
589 i = alc_pin_mode_min(dir);
Roel Kluin4b35d2ca2009-08-02 13:30:45 +0200590 while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100591 i++;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200592 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100593 return 0;
594}
595
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200596static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
597 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100598{
599 signed int change;
600 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
601 hda_nid_t nid = kcontrol->private_value & 0xffff;
602 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
603 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200604 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
605 AC_VERB_GET_PIN_WIDGET_CONTROL,
606 0x00);
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100607
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200608 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100609 val = alc_pin_mode_min(dir);
610
611 change = pinctl != alc_pin_mode_values[val];
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100612 if (change) {
613 /* Set pin mode to that requested */
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200614 snd_hda_codec_write_cache(codec, nid, 0,
615 AC_VERB_SET_PIN_WIDGET_CONTROL,
616 alc_pin_mode_values[val]);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100617
Kailang Yangea1fb292008-08-26 12:58:38 +0200618 /* Also enable the retasking pin's input/output as required
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100619 * for the requested pin mode. Enum values of 2 or less are
620 * input modes.
621 *
622 * Dynamically switching the input/output buffers probably
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200623 * reduces noise slightly (particularly on input) so we'll
624 * do it. However, having both input and output buffers
625 * enabled simultaneously doesn't seem to be problematic if
626 * this turns out to be necessary in the future.
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100627 */
628 if (val <= 2) {
Takashi Iwai47fd8302007-08-10 17:11:07 +0200629 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
630 HDA_AMP_MUTE, HDA_AMP_MUTE);
631 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
632 HDA_AMP_MUTE, 0);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100633 } else {
Takashi Iwai47fd8302007-08-10 17:11:07 +0200634 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
635 HDA_AMP_MUTE, HDA_AMP_MUTE);
636 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
637 HDA_AMP_MUTE, 0);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100638 }
639 }
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200640 return change;
641}
642
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100643#define ALC_PIN_MODE(xname, nid, dir) \
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200644 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100645 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100646 .info = alc_pin_mode_info, \
647 .get = alc_pin_mode_get, \
648 .put = alc_pin_mode_put, \
649 .private_value = nid | (dir<<16) }
Kailang Yangdf694da2005-12-05 19:42:22 +0100650
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100651/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
652 * together using a mask with more than one bit set. This control is
653 * currently used only by the ALC260 test model. At this stage they are not
654 * needed for any "production" models.
655 */
656#ifdef CONFIG_SND_DEBUG
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200657#define alc_gpio_data_info snd_ctl_boolean_mono_info
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200658
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200659static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
660 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100661{
662 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
663 hda_nid_t nid = kcontrol->private_value & 0xffff;
664 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
665 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200666 unsigned int val = snd_hda_codec_read(codec, nid, 0,
667 AC_VERB_GET_GPIO_DATA, 0x00);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100668
669 *valp = (val & mask) != 0;
670 return 0;
671}
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200672static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
673 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100674{
675 signed int change;
676 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
677 hda_nid_t nid = kcontrol->private_value & 0xffff;
678 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
679 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200680 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
681 AC_VERB_GET_GPIO_DATA,
682 0x00);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100683
684 /* Set/unset the masked GPIO bit(s) as needed */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200685 change = (val == 0 ? 0 : mask) != (gpio_data & mask);
686 if (val == 0)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100687 gpio_data &= ~mask;
688 else
689 gpio_data |= mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200690 snd_hda_codec_write_cache(codec, nid, 0,
691 AC_VERB_SET_GPIO_DATA, gpio_data);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100692
693 return change;
694}
695#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
696 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100697 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100698 .info = alc_gpio_data_info, \
699 .get = alc_gpio_data_get, \
700 .put = alc_gpio_data_put, \
701 .private_value = nid | (mask<<16) }
702#endif /* CONFIG_SND_DEBUG */
703
Jonathan Woithe92621f12006-02-28 11:47:47 +0100704/* A switch control to allow the enabling of the digital IO pins on the
705 * ALC260. This is incredibly simplistic; the intention of this control is
706 * to provide something in the test model allowing digital outputs to be
707 * identified if present. If models are found which can utilise these
708 * outputs a more complete mixer control can be devised for those models if
709 * necessary.
710 */
711#ifdef CONFIG_SND_DEBUG
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200712#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200713
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200714static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
715 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe92621f12006-02-28 11:47:47 +0100716{
717 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
718 hda_nid_t nid = kcontrol->private_value & 0xffff;
719 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
720 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200721 unsigned int val = snd_hda_codec_read(codec, nid, 0,
Andrew Paprocki3982d172007-12-19 12:13:44 +0100722 AC_VERB_GET_DIGI_CONVERT_1, 0x00);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100723
724 *valp = (val & mask) != 0;
725 return 0;
726}
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200727static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
728 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe92621f12006-02-28 11:47:47 +0100729{
730 signed int change;
731 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
732 hda_nid_t nid = kcontrol->private_value & 0xffff;
733 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
734 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200735 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
Andrew Paprocki3982d172007-12-19 12:13:44 +0100736 AC_VERB_GET_DIGI_CONVERT_1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200737 0x00);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100738
739 /* Set/unset the masked control bit(s) as needed */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200740 change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100741 if (val==0)
742 ctrl_data &= ~mask;
743 else
744 ctrl_data |= mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200745 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
746 ctrl_data);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100747
748 return change;
749}
750#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
751 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100752 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe92621f12006-02-28 11:47:47 +0100753 .info = alc_spdif_ctrl_info, \
754 .get = alc_spdif_ctrl_get, \
755 .put = alc_spdif_ctrl_put, \
756 .private_value = nid | (mask<<16) }
757#endif /* CONFIG_SND_DEBUG */
758
Jonathan Woithef8225f62008-01-08 12:16:54 +0100759/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
760 * Again, this is only used in the ALC26x test models to help identify when
761 * the EAPD line must be asserted for features to work.
762 */
763#ifdef CONFIG_SND_DEBUG
764#define alc_eapd_ctrl_info snd_ctl_boolean_mono_info
765
766static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
767 struct snd_ctl_elem_value *ucontrol)
768{
769 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
770 hda_nid_t nid = kcontrol->private_value & 0xffff;
771 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
772 long *valp = ucontrol->value.integer.value;
773 unsigned int val = snd_hda_codec_read(codec, nid, 0,
774 AC_VERB_GET_EAPD_BTLENABLE, 0x00);
775
776 *valp = (val & mask) != 0;
777 return 0;
778}
779
780static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
781 struct snd_ctl_elem_value *ucontrol)
782{
783 int change;
784 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
785 hda_nid_t nid = kcontrol->private_value & 0xffff;
786 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
787 long val = *ucontrol->value.integer.value;
788 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
789 AC_VERB_GET_EAPD_BTLENABLE,
790 0x00);
791
792 /* Set/unset the masked control bit(s) as needed */
793 change = (!val ? 0 : mask) != (ctrl_data & mask);
794 if (!val)
795 ctrl_data &= ~mask;
796 else
797 ctrl_data |= mask;
798 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
799 ctrl_data);
800
801 return change;
802}
803
804#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
805 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100806 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithef8225f62008-01-08 12:16:54 +0100807 .info = alc_eapd_ctrl_info, \
808 .get = alc_eapd_ctrl_get, \
809 .put = alc_eapd_ctrl_put, \
810 .private_value = nid | (mask<<16) }
811#endif /* CONFIG_SND_DEBUG */
812
Kailang Yangdf694da2005-12-05 19:42:22 +0100813/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100814 * set up the input pin config (depending on the given auto-pin type)
815 */
816static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
817 int auto_pin_type)
818{
819 unsigned int val = PIN_IN;
820
821 if (auto_pin_type <= AUTO_PIN_FRONT_MIC) {
822 unsigned int pincap;
Takashi Iwai1327a322009-03-23 13:07:47 +0100823 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100824 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
825 if (pincap & AC_PINCAP_VREF_80)
826 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200827 else if (pincap & AC_PINCAP_VREF_50)
828 val = PIN_VREF50;
829 else if (pincap & AC_PINCAP_VREF_100)
830 val = PIN_VREF100;
831 else if (pincap & AC_PINCAP_VREF_GRD)
832 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100833 }
834 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
835}
836
837/*
Takashi Iwaid88897e2008-10-31 15:01:37 +0100838 */
839static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
840{
841 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
842 return;
843 spec->mixers[spec->num_mixers++] = mix;
844}
845
846static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
847{
848 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
849 return;
850 spec->init_verbs[spec->num_init_verbs++] = verb;
851}
852
853/*
Kailang Yangdf694da2005-12-05 19:42:22 +0100854 * set up from the preset table
855 */
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200856static void setup_preset(struct hda_codec *codec,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200857 const struct alc_config_preset *preset)
Kailang Yangdf694da2005-12-05 19:42:22 +0100858{
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200859 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +0100860 int i;
861
862 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100863 add_mixer(spec, preset->mixers[i]);
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100864 spec->cap_mixer = preset->cap_mixer;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200865 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
866 i++)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100867 add_verb(spec, preset->init_verbs[i]);
Kailang Yangea1fb292008-08-26 12:58:38 +0200868
Kailang Yangdf694da2005-12-05 19:42:22 +0100869 spec->channel_mode = preset->channel_mode;
870 spec->num_channel_mode = preset->num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200871 spec->need_dac_fix = preset->need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200872 spec->const_channel_count = preset->const_channel_count;
Kailang Yangdf694da2005-12-05 19:42:22 +0100873
Hector Martin3b315d72009-06-02 10:54:19 +0200874 if (preset->const_channel_count)
875 spec->multiout.max_channels = preset->const_channel_count;
876 else
877 spec->multiout.max_channels = spec->channel_mode[0].channels;
878 spec->ext_channel_count = spec->channel_mode[0].channels;
Kailang Yangdf694da2005-12-05 19:42:22 +0100879
880 spec->multiout.num_dacs = preset->num_dacs;
881 spec->multiout.dac_nids = preset->dac_nids;
882 spec->multiout.dig_out_nid = preset->dig_out_nid;
Wu Fengguangb25c9da2009-02-06 15:02:27 +0800883 spec->multiout.slave_dig_outs = preset->slave_dig_outs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100884 spec->multiout.hp_nid = preset->hp_nid;
Kailang Yangea1fb292008-08-26 12:58:38 +0200885
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200886 spec->num_mux_defs = preset->num_mux_defs;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200887 if (!spec->num_mux_defs)
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200888 spec->num_mux_defs = 1;
Kailang Yangdf694da2005-12-05 19:42:22 +0100889 spec->input_mux = preset->input_mux;
890
891 spec->num_adc_nids = preset->num_adc_nids;
892 spec->adc_nids = preset->adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100893 spec->capsrc_nids = preset->capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +0100894 spec->dig_in_nid = preset->dig_in_nid;
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100895
896 spec->unsol_event = preset->unsol_event;
897 spec->init_hook = preset->init_hook;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200898#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +0100899 spec->power_hook = preset->power_hook;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200900 spec->loopback.amplist = preset->loopbacks;
901#endif
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200902
903 if (preset->setup)
904 preset->setup(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +0100905}
906
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200907/* Enable GPIO mask and set output */
908static struct hda_verb alc_gpio1_init_verbs[] = {
909 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
910 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
911 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
912 { }
913};
914
915static struct hda_verb alc_gpio2_init_verbs[] = {
916 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
917 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
918 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
919 { }
920};
921
Kailang Yangbdd148a2007-05-08 15:19:08 +0200922static struct hda_verb alc_gpio3_init_verbs[] = {
923 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
924 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
925 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
926 { }
927};
928
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200929/*
930 * Fix hardware PLL issue
931 * On some codecs, the analog PLL gating control must be off while
932 * the default value is 1.
933 */
934static void alc_fix_pll(struct hda_codec *codec)
935{
936 struct alc_spec *spec = codec->spec;
937 unsigned int val;
938
939 if (!spec->pll_nid)
940 return;
941 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
942 spec->pll_coef_idx);
943 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
944 AC_VERB_GET_PROC_COEF, 0);
945 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
946 spec->pll_coef_idx);
947 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
948 val & ~(1 << spec->pll_coef_bit));
949}
950
951static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
952 unsigned int coef_idx, unsigned int coef_bit)
953{
954 struct alc_spec *spec = codec->spec;
955 spec->pll_nid = nid;
956 spec->pll_coef_idx = coef_idx;
957 spec->pll_coef_bit = coef_bit;
958 alc_fix_pll(codec);
959}
960
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200961static void alc_automute_pin(struct hda_codec *codec)
Kailang Yangc9b58002007-10-16 14:30:01 +0200962{
963 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200964 unsigned int nid = spec->autocfg.hp_pins[0];
965 int i;
Kailang Yangc9b58002007-10-16 14:30:01 +0200966
Takashi Iwaiad87c642009-11-02 14:23:15 +0100967 if (!nid)
968 return;
Wu Fengguang864f92b2009-11-18 12:38:02 +0800969 spec->jack_present = snd_hda_jack_detect(codec, nid);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200970 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
971 nid = spec->autocfg.speaker_pins[i];
972 if (!nid)
973 break;
974 snd_hda_codec_write(codec, nid, 0,
975 AC_VERB_SET_PIN_WIDGET_CONTROL,
976 spec->jack_present ? 0 : PIN_OUT);
977 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200978}
979
Takashi Iwai6c819492009-08-10 18:47:44 +0200980static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
981 hda_nid_t nid)
982{
983 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
984 int i, nums;
985
986 nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
987 for (i = 0; i < nums; i++)
988 if (conn[i] == nid)
989 return i;
990 return -1;
991}
992
Kailang Yang7fb0d782008-10-15 11:12:35 +0200993static void alc_mic_automute(struct hda_codec *codec)
994{
995 struct alc_spec *spec = codec->spec;
Takashi Iwai6c819492009-08-10 18:47:44 +0200996 struct alc_mic_route *dead, *alive;
997 unsigned int present, type;
998 hda_nid_t cap_nid;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200999
Takashi Iwaib59bdf32009-08-11 09:47:30 +02001000 if (!spec->auto_mic)
1001 return;
Takashi Iwai6c819492009-08-10 18:47:44 +02001002 if (!spec->int_mic.pin || !spec->ext_mic.pin)
1003 return;
1004 if (snd_BUG_ON(!spec->adc_nids))
1005 return;
1006
1007 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
1008
Wu Fengguang864f92b2009-11-18 12:38:02 +08001009 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
Takashi Iwai6c819492009-08-10 18:47:44 +02001010 if (present) {
1011 alive = &spec->ext_mic;
1012 dead = &spec->int_mic;
1013 } else {
1014 alive = &spec->int_mic;
1015 dead = &spec->ext_mic;
1016 }
1017
Takashi Iwai6c819492009-08-10 18:47:44 +02001018 type = get_wcaps_type(get_wcaps(codec, cap_nid));
1019 if (type == AC_WID_AUD_MIX) {
1020 /* Matrix-mixer style (e.g. ALC882) */
1021 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1022 alive->mux_idx,
1023 HDA_AMP_MUTE, 0);
1024 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1025 dead->mux_idx,
1026 HDA_AMP_MUTE, HDA_AMP_MUTE);
1027 } else {
1028 /* MUX style (e.g. ALC880) */
1029 snd_hda_codec_write_cache(codec, cap_nid, 0,
1030 AC_VERB_SET_CONNECT_SEL,
1031 alive->mux_idx);
1032 }
1033
1034 /* FIXME: analog mixer */
Kailang Yang7fb0d782008-10-15 11:12:35 +02001035}
1036
Kailang Yangc9b58002007-10-16 14:30:01 +02001037/* unsolicited event for HP jack sensing */
1038static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
1039{
1040 if (codec->vendor_id == 0x10ec0880)
1041 res >>= 28;
1042 else
1043 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001044 switch (res) {
1045 case ALC880_HP_EVENT:
1046 alc_automute_pin(codec);
1047 break;
1048 case ALC880_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +02001049 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001050 break;
1051 }
Kailang Yang7fb0d782008-10-15 11:12:35 +02001052}
1053
1054static void alc_inithook(struct hda_codec *codec)
1055{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001056 alc_automute_pin(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +02001057 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +02001058}
1059
Kailang Yangf9423e72008-05-27 12:32:25 +02001060/* additional initialization for ALC888 variants */
1061static void alc888_coef_init(struct hda_codec *codec)
1062{
1063 unsigned int tmp;
1064
1065 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
1066 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1067 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +01001068 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +02001069 /* alc888S-VC */
1070 snd_hda_codec_read(codec, 0x20, 0,
1071 AC_VERB_SET_PROC_COEF, 0x830);
1072 else
1073 /* alc888-VB */
1074 snd_hda_codec_read(codec, 0x20, 0,
1075 AC_VERB_SET_PROC_COEF, 0x3030);
1076}
1077
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02001078static void alc889_coef_init(struct hda_codec *codec)
1079{
1080 unsigned int tmp;
1081
1082 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1083 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1084 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1085 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
1086}
1087
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001088/* turn on/off EAPD control (only if available) */
1089static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
1090{
1091 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
1092 return;
1093 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
1094 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
1095 on ? 2 : 0);
1096}
1097
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001098static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001099{
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001100 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001101
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001102 switch (type) {
1103 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001104 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
1105 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001106 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001107 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
1108 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001109 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001110 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
1111 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001112 case ALC_INIT_DEFAULT:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001113 switch (codec->vendor_id) {
Kailang Yangc9b58002007-10-16 14:30:01 +02001114 case 0x10ec0260:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001115 set_eapd(codec, 0x0f, 1);
1116 set_eapd(codec, 0x10, 1);
Kailang Yangc9b58002007-10-16 14:30:01 +02001117 break;
1118 case 0x10ec0262:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001119 case 0x10ec0267:
1120 case 0x10ec0268:
Kailang Yangc9b58002007-10-16 14:30:01 +02001121 case 0x10ec0269:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001122 case 0x10ec0270:
Takashi Iwaic6e8f2d2009-02-06 12:45:52 +01001123 case 0x10ec0272:
Kailang Yangf9423e72008-05-27 12:32:25 +02001124 case 0x10ec0660:
1125 case 0x10ec0662:
1126 case 0x10ec0663:
Kailang Yangc9b58002007-10-16 14:30:01 +02001127 case 0x10ec0862:
Takashi Iwai20a3a052008-05-23 17:52:53 +02001128 case 0x10ec0889:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001129 set_eapd(codec, 0x14, 1);
1130 set_eapd(codec, 0x15, 1);
Kailang Yangc9b58002007-10-16 14:30:01 +02001131 break;
Kailang Yangbdd148a2007-05-08 15:19:08 +02001132 }
Kailang Yangc9b58002007-10-16 14:30:01 +02001133 switch (codec->vendor_id) {
1134 case 0x10ec0260:
1135 snd_hda_codec_write(codec, 0x1a, 0,
1136 AC_VERB_SET_COEF_INDEX, 7);
1137 tmp = snd_hda_codec_read(codec, 0x1a, 0,
1138 AC_VERB_GET_PROC_COEF, 0);
1139 snd_hda_codec_write(codec, 0x1a, 0,
1140 AC_VERB_SET_COEF_INDEX, 7);
1141 snd_hda_codec_write(codec, 0x1a, 0,
1142 AC_VERB_SET_PROC_COEF,
1143 tmp | 0x2010);
1144 break;
1145 case 0x10ec0262:
1146 case 0x10ec0880:
1147 case 0x10ec0882:
1148 case 0x10ec0883:
1149 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +01001150 case 0x10ec0887:
Takashi Iwai20a3a052008-05-23 17:52:53 +02001151 case 0x10ec0889:
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02001152 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +02001153 break;
Kailang Yangf9423e72008-05-27 12:32:25 +02001154 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001155 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +02001156 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +01001157#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +02001158 case 0x10ec0267:
1159 case 0x10ec0268:
1160 snd_hda_codec_write(codec, 0x20, 0,
1161 AC_VERB_SET_COEF_INDEX, 7);
1162 tmp = snd_hda_codec_read(codec, 0x20, 0,
1163 AC_VERB_GET_PROC_COEF, 0);
1164 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +02001165 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +02001166 snd_hda_codec_write(codec, 0x20, 0,
1167 AC_VERB_SET_PROC_COEF,
1168 tmp | 0x3000);
1169 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +01001170#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001171 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001172 break;
1173 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001174}
Kailang Yangea1fb292008-08-26 12:58:38 +02001175
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001176static void alc_init_auto_hp(struct hda_codec *codec)
1177{
1178 struct alc_spec *spec = codec->spec;
1179
1180 if (!spec->autocfg.hp_pins[0])
Kailang Yangc9b58002007-10-16 14:30:01 +02001181 return;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001182
Kailang Yangc9b58002007-10-16 14:30:01 +02001183 if (!spec->autocfg.speaker_pins[0]) {
Takashi Iwai2a2ed0d2009-04-28 13:01:26 +02001184 if (spec->autocfg.line_out_pins[0] &&
1185 spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
Kailang Yangc9b58002007-10-16 14:30:01 +02001186 spec->autocfg.speaker_pins[0] =
Kailang Yang8c427222008-01-10 13:03:59 +01001187 spec->autocfg.line_out_pins[0];
Kailang Yangc9b58002007-10-16 14:30:01 +02001188 else
1189 return;
1190 }
1191
Takashi Iwai2a2ed0d2009-04-28 13:01:26 +02001192 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
1193 spec->autocfg.hp_pins[0]);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001194 snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0,
1195 AC_VERB_SET_UNSOLICITED_ENABLE,
1196 AC_USRSP_EN | ALC880_HP_EVENT);
1197 spec->unsol_event = alc_sku_unsol_event;
1198}
1199
Takashi Iwai6c819492009-08-10 18:47:44 +02001200static void alc_init_auto_mic(struct hda_codec *codec)
1201{
1202 struct alc_spec *spec = codec->spec;
1203 struct auto_pin_cfg *cfg = &spec->autocfg;
1204 hda_nid_t fixed, ext;
1205 int i;
1206
1207 /* there must be only two mic inputs exclusively */
1208 for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++)
1209 if (cfg->input_pins[i])
1210 return;
1211
1212 fixed = ext = 0;
1213 for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) {
1214 hda_nid_t nid = cfg->input_pins[i];
1215 unsigned int defcfg;
1216 if (!nid)
1217 return;
1218 defcfg = snd_hda_codec_get_pincfg(codec, nid);
1219 switch (get_defcfg_connect(defcfg)) {
1220 case AC_JACK_PORT_FIXED:
1221 if (fixed)
1222 return; /* already occupied */
1223 fixed = nid;
1224 break;
1225 case AC_JACK_PORT_COMPLEX:
1226 if (ext)
1227 return; /* already occupied */
1228 ext = nid;
1229 break;
1230 default:
1231 return; /* invalid entry */
1232 }
1233 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001234 if (!ext || !fixed)
1235 return;
Takashi Iwai6c819492009-08-10 18:47:44 +02001236 if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
1237 return; /* no unsol support */
1238 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
1239 ext, fixed);
1240 spec->ext_mic.pin = ext;
1241 spec->int_mic.pin = fixed;
1242 spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1243 spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1244 spec->auto_mic = 1;
1245 snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
1246 AC_VERB_SET_UNSOLICITED_ENABLE,
1247 AC_USRSP_EN | ALC880_MIC_EVENT);
1248 spec->unsol_event = alc_sku_unsol_event;
1249}
1250
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001251/* check subsystem ID and set up device-specific initialization;
1252 * return 1 if initialized, 0 if invalid SSID
1253 */
1254/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1255 * 31 ~ 16 : Manufacture ID
1256 * 15 ~ 8 : SKU ID
1257 * 7 ~ 0 : Assembly ID
1258 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1259 */
1260static int alc_subsystem_id(struct hda_codec *codec,
1261 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001262 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001263{
1264 unsigned int ass, tmp, i;
1265 unsigned nid;
1266 struct alc_spec *spec = codec->spec;
1267
1268 ass = codec->subsystem_id & 0xffff;
1269 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1270 goto do_sku;
1271
1272 /* invalid SSID, check the special NID pin defcfg instead */
1273 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001274 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001275 * 29~21 : reserve
1276 * 20 : PCBEEP input
1277 * 19~16 : Check sum (15:1)
1278 * 15~1 : Custom
1279 * 0 : override
1280 */
1281 nid = 0x1d;
1282 if (codec->vendor_id == 0x10ec0260)
1283 nid = 0x17;
1284 ass = snd_hda_codec_get_pincfg(codec, nid);
1285 snd_printd("realtek: No valid SSID, "
1286 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001287 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001288 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001289 return 0;
1290 if ((ass >> 30) != 1) /* no physical connection */
1291 return 0;
1292
1293 /* check sum */
1294 tmp = 0;
1295 for (i = 1; i < 16; i++) {
1296 if ((ass >> i) & 1)
1297 tmp++;
1298 }
1299 if (((ass >> 16) & 0xf) != tmp)
1300 return 0;
1301do_sku:
1302 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1303 ass & 0xffff, codec->vendor_id);
1304 /*
1305 * 0 : override
1306 * 1 : Swap Jack
1307 * 2 : 0 --> Desktop, 1 --> Laptop
1308 * 3~5 : External Amplifier control
1309 * 7~6 : Reserved
1310 */
1311 tmp = (ass & 0x38) >> 3; /* external Amp control */
1312 switch (tmp) {
1313 case 1:
1314 spec->init_amp = ALC_INIT_GPIO1;
1315 break;
1316 case 3:
1317 spec->init_amp = ALC_INIT_GPIO2;
1318 break;
1319 case 7:
1320 spec->init_amp = ALC_INIT_GPIO3;
1321 break;
1322 case 5:
1323 spec->init_amp = ALC_INIT_DEFAULT;
1324 break;
1325 }
1326
1327 /* is laptop or Desktop and enable the function "Mute internal speaker
1328 * when the external headphone out jack is plugged"
1329 */
1330 if (!(ass & 0x8000))
1331 return 1;
1332 /*
1333 * 10~8 : Jack location
1334 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1335 * 14~13: Resvered
1336 * 15 : 1 --> enable the function "Mute internal speaker
1337 * when the external headphone out jack is plugged"
1338 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001339 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001340 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001341 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1342 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001343 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001344 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001345 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001346 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001347 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001348 else if (tmp == 3)
1349 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001350 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001351 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001352 for (i = 0; i < spec->autocfg.line_outs; i++)
1353 if (spec->autocfg.line_out_pins[i] == nid)
1354 return 1;
1355 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001356 }
1357
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001358 alc_init_auto_hp(codec);
Takashi Iwai6c819492009-08-10 18:47:44 +02001359 alc_init_auto_mic(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001360 return 1;
1361}
Kailang Yangea1fb292008-08-26 12:58:38 +02001362
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001363static void alc_ssid_check(struct hda_codec *codec,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001364 hda_nid_t porta, hda_nid_t porte,
1365 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001366{
Kailang Yang6227cdc2010-02-25 08:36:52 +01001367 if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001368 struct alc_spec *spec = codec->spec;
1369 snd_printd("realtek: "
1370 "Enable default setup for auto mode as fallback\n");
1371 spec->init_amp = ALC_INIT_DEFAULT;
1372 alc_init_auto_hp(codec);
Takashi Iwai6c819492009-08-10 18:47:44 +02001373 alc_init_auto_mic(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001374 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001375}
1376
Takashi Iwai41e41f12005-06-08 14:48:49 +02001377/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001378 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001379 */
1380
1381struct alc_pincfg {
1382 hda_nid_t nid;
1383 u32 val;
1384};
1385
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001386struct alc_fixup {
1387 const struct alc_pincfg *pins;
1388 const struct hda_verb *verbs;
1389};
1390
1391static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaif95474e2007-07-10 00:47:43 +02001392 const struct snd_pci_quirk *quirk,
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001393 const struct alc_fixup *fix)
Takashi Iwaif95474e2007-07-10 00:47:43 +02001394{
1395 const struct alc_pincfg *cfg;
1396
1397 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1398 if (!quirk)
1399 return;
1400
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001401 fix += quirk->value;
1402 cfg = fix->pins;
1403 if (cfg) {
1404 for (; cfg->nid; cfg++)
1405 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
1406 }
1407 if (fix->verbs)
1408 add_verb(codec->spec, fix->verbs);
Takashi Iwaif95474e2007-07-10 00:47:43 +02001409}
1410
Kailang Yang274693f2009-12-03 10:07:50 +01001411static int alc_read_coef_idx(struct hda_codec *codec,
1412 unsigned int coef_idx)
1413{
1414 unsigned int val;
1415 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1416 coef_idx);
1417 val = snd_hda_codec_read(codec, 0x20, 0,
1418 AC_VERB_GET_PROC_COEF, 0);
1419 return val;
1420}
1421
Takashi Iwaif95474e2007-07-10 00:47:43 +02001422/*
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001423 * ALC888
1424 */
1425
1426/*
1427 * 2ch mode
1428 */
1429static struct hda_verb alc888_4ST_ch2_intel_init[] = {
1430/* Mic-in jack as mic in */
1431 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1432 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1433/* Line-in jack as Line in */
1434 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1435 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1436/* Line-Out as Front */
1437 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1438 { } /* end */
1439};
1440
1441/*
1442 * 4ch mode
1443 */
1444static struct hda_verb alc888_4ST_ch4_intel_init[] = {
1445/* Mic-in jack as mic in */
1446 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1447 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1448/* Line-in jack as Surround */
1449 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1450 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1451/* Line-Out as Front */
1452 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1453 { } /* end */
1454};
1455
1456/*
1457 * 6ch mode
1458 */
1459static struct hda_verb alc888_4ST_ch6_intel_init[] = {
1460/* Mic-in jack as CLFE */
1461 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1462 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1463/* Line-in jack as Surround */
1464 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1465 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1466/* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
1467 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1468 { } /* end */
1469};
1470
1471/*
1472 * 8ch mode
1473 */
1474static struct hda_verb alc888_4ST_ch8_intel_init[] = {
1475/* Mic-in jack as CLFE */
1476 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1477 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1478/* Line-in jack as Surround */
1479 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1480 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1481/* Line-Out as Side */
1482 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1483 { } /* end */
1484};
1485
1486static struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
1487 { 2, alc888_4ST_ch2_intel_init },
1488 { 4, alc888_4ST_ch4_intel_init },
1489 { 6, alc888_4ST_ch6_intel_init },
1490 { 8, alc888_4ST_ch8_intel_init },
1491};
1492
1493/*
1494 * ALC888 Fujitsu Siemens Amillo xa3530
1495 */
1496
1497static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
1498/* Front Mic: set to PIN_IN (empty by default) */
1499 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1500/* Connect Internal HP to Front */
1501 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1502 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1503 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1504/* Connect Bass HP to Front */
1505 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1506 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1507 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1508/* Connect Line-Out side jack (SPDIF) to Side */
1509 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1510 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1511 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1512/* Connect Mic jack to CLFE */
1513 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1514 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1515 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
1516/* Connect Line-in jack to Surround */
1517 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1518 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1519 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
1520/* Connect HP out jack to Front */
1521 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1522 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1523 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1524/* Enable unsolicited event for HP jack and Line-out jack */
1525 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1526 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1527 {}
1528};
1529
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001530static void alc_automute_amp(struct hda_codec *codec)
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001531{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001532 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +08001533 unsigned int mute;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001534 hda_nid_t nid;
1535 int i;
1536
1537 spec->jack_present = 0;
1538 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
1539 nid = spec->autocfg.hp_pins[i];
1540 if (!nid)
1541 break;
Wu Fengguang864f92b2009-11-18 12:38:02 +08001542 if (snd_hda_jack_detect(codec, nid)) {
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001543 spec->jack_present = 1;
1544 break;
1545 }
1546 }
1547
1548 mute = spec->jack_present ? HDA_AMP_MUTE : 0;
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001549 /* Toggle internal speakers muting */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001550 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
1551 nid = spec->autocfg.speaker_pins[i];
1552 if (!nid)
1553 break;
1554 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1555 HDA_AMP_MUTE, mute);
1556 }
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001557}
1558
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001559static void alc_automute_amp_unsol_event(struct hda_codec *codec,
1560 unsigned int res)
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001561{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001562 if (codec->vendor_id == 0x10ec0880)
1563 res >>= 28;
1564 else
1565 res >>= 26;
1566 if (res == ALC880_HP_EVENT)
1567 alc_automute_amp(codec);
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001568}
1569
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001570static void alc889_automute_setup(struct hda_codec *codec)
Wu Fengguang6732bd02009-07-30 09:19:14 +02001571{
1572 struct alc_spec *spec = codec->spec;
1573
1574 spec->autocfg.hp_pins[0] = 0x15;
1575 spec->autocfg.speaker_pins[0] = 0x14;
1576 spec->autocfg.speaker_pins[1] = 0x16;
1577 spec->autocfg.speaker_pins[2] = 0x17;
1578 spec->autocfg.speaker_pins[3] = 0x19;
1579 spec->autocfg.speaker_pins[4] = 0x1a;
Wu Fengguang6732bd02009-07-30 09:19:14 +02001580}
1581
1582static void alc889_intel_init_hook(struct hda_codec *codec)
1583{
1584 alc889_coef_init(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001585 alc_automute_amp(codec);
Wu Fengguang6732bd02009-07-30 09:19:14 +02001586}
1587
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001588static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001589{
1590 struct alc_spec *spec = codec->spec;
1591
1592 spec->autocfg.hp_pins[0] = 0x17; /* line-out */
1593 spec->autocfg.hp_pins[1] = 0x1b; /* hp */
1594 spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
1595 spec->autocfg.speaker_pins[1] = 0x15; /* bass */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001596}
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001597
1598/*
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001599 * ALC888 Acer Aspire 4930G model
1600 */
1601
1602static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
1603/* Front Mic: set to PIN_IN (empty by default) */
1604 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1605/* Unselect Front Mic by default in input mixer 3 */
1606 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001607/* Enable unsolicited event for HP jack */
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001608 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1609/* Connect Internal HP to front */
1610 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1611 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1612 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1613/* Connect HP out to front */
1614 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1615 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1616 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1617 { }
1618};
1619
Hector Martin3b315d72009-06-02 10:54:19 +02001620/*
Tony Vroond2fd4b02009-06-21 00:40:10 +01001621 * ALC888 Acer Aspire 6530G model
1622 */
1623
1624static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
Tony Vroond1284182010-04-05 16:30:43 +01001625/* Route to built-in subwoofer as well as speakers */
1626 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1627 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1628 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1629 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001630/* Bias voltage on for external mic port */
1631 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
Emilio López320d5922009-06-25 08:18:44 +02001632/* Front Mic: set to PIN_IN (empty by default) */
1633 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1634/* Unselect Front Mic by default in input mixer 3 */
1635 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001636/* Enable unsolicited event for HP jack */
1637 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1638/* Enable speaker output */
1639 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1640 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Tony Vroond1284182010-04-05 16:30:43 +01001641 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001642/* Enable headphone output */
1643 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
1644 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1645 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
Tony Vroond1284182010-04-05 16:30:43 +01001646 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001647 { }
1648};
1649
1650/*
Hector Martin018df412009-06-04 00:13:40 +02001651 * ALC889 Acer Aspire 8930G model
Hector Martin3b315d72009-06-02 10:54:19 +02001652 */
1653
Hector Martin018df412009-06-04 00:13:40 +02001654static struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
Hector Martin3b315d72009-06-02 10:54:19 +02001655/* Front Mic: set to PIN_IN (empty by default) */
1656 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1657/* Unselect Front Mic by default in input mixer 3 */
1658 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
1659/* Enable unsolicited event for HP jack */
1660 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1661/* Connect Internal Front to Front */
1662 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1663 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1664 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1665/* Connect Internal Rear to Rear */
1666 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1667 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1668 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
1669/* Connect Internal CLFE to CLFE */
1670 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1671 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1672 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
1673/* Connect HP out to Front */
Hector Martin018df412009-06-04 00:13:40 +02001674 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
Hector Martin3b315d72009-06-02 10:54:19 +02001675 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1676 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1677/* Enable all DACs */
1678/* DAC DISABLE/MUTE 1? */
1679/* setting bits 1-5 disables DAC nids 0x02-0x06 apparently. Init=0x38 */
1680 {0x20, AC_VERB_SET_COEF_INDEX, 0x03},
1681 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
1682/* DAC DISABLE/MUTE 2? */
1683/* some bit here disables the other DACs. Init=0x4900 */
1684 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
1685 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
Hector Martin018df412009-06-04 00:13:40 +02001686/* DMIC fix
1687 * This laptop has a stereo digital microphone. The mics are only 1cm apart
1688 * which makes the stereo useless. However, either the mic or the ALC889
1689 * makes the signal become a difference/sum signal instead of standard
1690 * stereo, which is annoying. So instead we flip this bit which makes the
1691 * codec replicate the sum signal to both channels, turning it into a
1692 * normal mono mic.
1693 */
1694/* DMIC_CONTROL? Init value = 0x0001 */
1695 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
1696 {0x20, AC_VERB_SET_PROC_COEF, 0x0003},
Hector Martin3b315d72009-06-02 10:54:19 +02001697 { }
1698};
1699
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001700static struct hda_input_mux alc888_2_capture_sources[2] = {
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001701 /* Front mic only available on one ADC */
1702 {
1703 .num_items = 4,
1704 .items = {
1705 { "Mic", 0x0 },
1706 { "Line", 0x2 },
1707 { "CD", 0x4 },
1708 { "Front Mic", 0xb },
1709 },
1710 },
1711 {
1712 .num_items = 3,
1713 .items = {
1714 { "Mic", 0x0 },
1715 { "Line", 0x2 },
1716 { "CD", 0x4 },
1717 },
1718 }
1719};
1720
Tony Vroond2fd4b02009-06-21 00:40:10 +01001721static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
1722 /* Interal mic only available on one ADC */
1723 {
Tony Vroon684a8842009-06-26 09:27:50 +01001724 .num_items = 5,
Tony Vroond2fd4b02009-06-21 00:40:10 +01001725 .items = {
1726 { "Ext Mic", 0x0 },
Tony Vroon684a8842009-06-26 09:27:50 +01001727 { "Line In", 0x2 },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001728 { "CD", 0x4 },
Tony Vroon684a8842009-06-26 09:27:50 +01001729 { "Input Mix", 0xa },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001730 { "Int Mic", 0xb },
1731 },
1732 },
1733 {
Tony Vroon684a8842009-06-26 09:27:50 +01001734 .num_items = 4,
Tony Vroond2fd4b02009-06-21 00:40:10 +01001735 .items = {
1736 { "Ext Mic", 0x0 },
Tony Vroon684a8842009-06-26 09:27:50 +01001737 { "Line In", 0x2 },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001738 { "CD", 0x4 },
Tony Vroon684a8842009-06-26 09:27:50 +01001739 { "Input Mix", 0xa },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001740 },
1741 }
1742};
1743
Hector Martin018df412009-06-04 00:13:40 +02001744static struct hda_input_mux alc889_capture_sources[3] = {
1745 /* Digital mic only available on first "ADC" */
1746 {
1747 .num_items = 5,
1748 .items = {
1749 { "Mic", 0x0 },
1750 { "Line", 0x2 },
1751 { "CD", 0x4 },
1752 { "Front Mic", 0xb },
1753 { "Input Mix", 0xa },
1754 },
1755 },
1756 {
1757 .num_items = 4,
1758 .items = {
1759 { "Mic", 0x0 },
1760 { "Line", 0x2 },
1761 { "CD", 0x4 },
1762 { "Input Mix", 0xa },
1763 },
1764 },
1765 {
1766 .num_items = 4,
1767 .items = {
1768 { "Mic", 0x0 },
1769 { "Line", 0x2 },
1770 { "CD", 0x4 },
1771 { "Input Mix", 0xa },
1772 },
1773 }
1774};
1775
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001776static struct snd_kcontrol_new alc888_base_mixer[] = {
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001777 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1778 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1779 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1780 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1781 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
1782 HDA_OUTPUT),
1783 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1784 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1785 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1786 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1787 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1788 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1789 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1790 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1791 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1792 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1793 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
1794 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001795 { } /* end */
1796};
1797
Hector Martin556eea92009-12-20 22:51:23 +01001798static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
1799 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1800 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1801 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1802 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1803 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
1804 HDA_OUTPUT),
1805 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1806 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1807 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1808 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1809 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1810 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1811 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
1812 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1813 { } /* end */
1814};
1815
1816
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001817static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001818{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001819 struct alc_spec *spec = codec->spec;
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001820
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001821 spec->autocfg.hp_pins[0] = 0x15;
1822 spec->autocfg.speaker_pins[0] = 0x14;
Łukasz Wojniłowicz7cef4cf2009-11-20 12:14:35 +01001823 spec->autocfg.speaker_pins[1] = 0x16;
1824 spec->autocfg.speaker_pins[2] = 0x17;
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001825}
1826
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001827static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
Emilio López320d5922009-06-25 08:18:44 +02001828{
1829 struct alc_spec *spec = codec->spec;
1830
1831 spec->autocfg.hp_pins[0] = 0x15;
1832 spec->autocfg.speaker_pins[0] = 0x14;
1833 spec->autocfg.speaker_pins[1] = 0x16;
1834 spec->autocfg.speaker_pins[2] = 0x17;
Emilio López320d5922009-06-25 08:18:44 +02001835}
1836
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001837static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
Hector Martin3b315d72009-06-02 10:54:19 +02001838{
1839 struct alc_spec *spec = codec->spec;
1840
1841 spec->autocfg.hp_pins[0] = 0x15;
1842 spec->autocfg.speaker_pins[0] = 0x14;
1843 spec->autocfg.speaker_pins[1] = 0x16;
1844 spec->autocfg.speaker_pins[2] = 0x1b;
Hector Martin3b315d72009-06-02 10:54:19 +02001845}
1846
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001847/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001848 * ALC880 3-stack model
1849 *
1850 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001851 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
1852 * F-Mic = 0x1b, HP = 0x19
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 */
1854
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001855static hda_nid_t alc880_dac_nids[4] = {
1856 /* front, rear, clfe, rear_surr */
1857 0x02, 0x05, 0x04, 0x03
1858};
1859
1860static hda_nid_t alc880_adc_nids[3] = {
1861 /* ADC0-2 */
1862 0x07, 0x08, 0x09,
1863};
1864
1865/* The datasheet says the node 0x07 is connected from inputs,
1866 * but it shows zero connection in the real implementation on some devices.
Kailang Yangdf694da2005-12-05 19:42:22 +01001867 * Note: this is a 915GAV bug, fixed on 915GLV
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001869static hda_nid_t alc880_adc_nids_alt[2] = {
1870 /* ADC1-2 */
1871 0x08, 0x09,
1872};
1873
1874#define ALC880_DIGOUT_NID 0x06
1875#define ALC880_DIGIN_NID 0x0a
1876
1877static struct hda_input_mux alc880_capture_source = {
1878 .num_items = 4,
1879 .items = {
1880 { "Mic", 0x0 },
1881 { "Front Mic", 0x3 },
1882 { "Line", 0x2 },
1883 { "CD", 0x4 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001885};
1886
1887/* channel source setting (2/6 channel selection for 3-stack) */
1888/* 2ch mode */
1889static struct hda_verb alc880_threestack_ch2_init[] = {
1890 /* set line-in to input, mute it */
1891 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1892 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1893 /* set mic-in to input vref 80%, mute it */
1894 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1895 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 { } /* end */
1897};
1898
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001899/* 6ch mode */
1900static struct hda_verb alc880_threestack_ch6_init[] = {
1901 /* set line-in to output, unmute it */
1902 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1903 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1904 /* set mic-in to output, unmute it */
1905 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1906 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1907 { } /* end */
1908};
1909
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01001910static struct hda_channel_mode alc880_threestack_modes[2] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001911 { 2, alc880_threestack_ch2_init },
1912 { 6, alc880_threestack_ch6_init },
1913};
1914
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01001915static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02001916 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01001917 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02001918 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01001919 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02001920 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1921 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01001922 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1923 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1925 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1926 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1927 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1928 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1929 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1930 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
1931 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001933 {
1934 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1935 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01001936 .info = alc_ch_mode_info,
1937 .get = alc_ch_mode_get,
1938 .put = alc_ch_mode_put,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001939 },
1940 { } /* end */
1941};
1942
1943/* capture mixer elements */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001944static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1945 struct snd_ctl_elem_info *uinfo)
1946{
1947 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1948 struct alc_spec *spec = codec->spec;
1949 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001950
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001951 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001952 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
1953 HDA_INPUT);
1954 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001955 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001956 return err;
1957}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001959static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1960 unsigned int size, unsigned int __user *tlv)
1961{
1962 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1963 struct alc_spec *spec = codec->spec;
1964 int err;
1965
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001966 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001967 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
1968 HDA_INPUT);
1969 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001970 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001971 return err;
1972}
1973
1974typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1975 struct snd_ctl_elem_value *ucontrol);
1976
1977static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1978 struct snd_ctl_elem_value *ucontrol,
1979 getput_call_t func)
1980{
1981 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1982 struct alc_spec *spec = codec->spec;
1983 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1984 int err;
1985
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001986 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001987 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx],
1988 3, 0, HDA_INPUT);
1989 err = func(kcontrol, ucontrol);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001990 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001991 return err;
1992}
1993
1994static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1995 struct snd_ctl_elem_value *ucontrol)
1996{
1997 return alc_cap_getput_caller(kcontrol, ucontrol,
1998 snd_hda_mixer_amp_volume_get);
1999}
2000
2001static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
2002 struct snd_ctl_elem_value *ucontrol)
2003{
2004 return alc_cap_getput_caller(kcontrol, ucontrol,
2005 snd_hda_mixer_amp_volume_put);
2006}
2007
2008/* capture mixer elements */
2009#define alc_cap_sw_info snd_ctl_boolean_stereo_info
2010
2011static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
2012 struct snd_ctl_elem_value *ucontrol)
2013{
2014 return alc_cap_getput_caller(kcontrol, ucontrol,
2015 snd_hda_mixer_amp_switch_get);
2016}
2017
2018static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
2019 struct snd_ctl_elem_value *ucontrol)
2020{
2021 return alc_cap_getput_caller(kcontrol, ucontrol,
2022 snd_hda_mixer_amp_switch_put);
2023}
2024
Takashi Iwaia23b6882009-03-23 15:21:36 +01002025#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002026 { \
2027 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2028 .name = "Capture Switch", \
2029 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
2030 .count = num, \
2031 .info = alc_cap_sw_info, \
2032 .get = alc_cap_sw_get, \
2033 .put = alc_cap_sw_put, \
2034 }, \
2035 { \
2036 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2037 .name = "Capture Volume", \
2038 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2039 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
2040 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
2041 .count = num, \
2042 .info = alc_cap_vol_info, \
2043 .get = alc_cap_vol_get, \
2044 .put = alc_cap_vol_put, \
2045 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01002046 }
2047
2048#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01002049 { \
2050 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2051 /* .name = "Capture Source", */ \
2052 .name = "Input Source", \
2053 .count = num, \
2054 .info = alc_mux_enum_info, \
2055 .get = alc_mux_enum_get, \
2056 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01002057 }
2058
2059#define DEFINE_CAPMIX(num) \
2060static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
2061 _DEFINE_CAPMIX(num), \
2062 _DEFINE_CAPSRC(num), \
2063 { } /* end */ \
2064}
2065
2066#define DEFINE_CAPMIX_NOSRC(num) \
2067static struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
2068 _DEFINE_CAPMIX(num), \
2069 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002070}
2071
2072/* up to three ADCs */
2073DEFINE_CAPMIX(1);
2074DEFINE_CAPMIX(2);
2075DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01002076DEFINE_CAPMIX_NOSRC(1);
2077DEFINE_CAPMIX_NOSRC(2);
2078DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002079
2080/*
2081 * ALC880 5-stack model
2082 *
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002083 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
2084 * Side = 0x02 (0xd)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002085 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
2086 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
2087 */
2088
2089/* additional mixers to alc880_three_stack_mixer */
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002090static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002091 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002092 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 { } /* end */
2094};
2095
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002096/* channel source setting (6/8 channel selection for 5-stack) */
2097/* 6ch mode */
2098static struct hda_verb alc880_fivestack_ch6_init[] = {
2099 /* set line-in to input, mute it */
2100 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2101 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002102 { } /* end */
2103};
2104
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002105/* 8ch mode */
2106static struct hda_verb alc880_fivestack_ch8_init[] = {
2107 /* set line-in to output, unmute it */
2108 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2109 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2110 { } /* end */
2111};
2112
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002113static struct hda_channel_mode alc880_fivestack_modes[2] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002114 { 6, alc880_fivestack_ch6_init },
2115 { 8, alc880_fivestack_ch8_init },
2116};
2117
2118
2119/*
2120 * ALC880 6-stack model
2121 *
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002122 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
2123 * Side = 0x05 (0x0f)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002124 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
2125 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
2126 */
2127
2128static hda_nid_t alc880_6st_dac_nids[4] = {
2129 /* front, rear, clfe, rear_surr */
2130 0x02, 0x03, 0x04, 0x05
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002131};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002132
2133static struct hda_input_mux alc880_6stack_capture_source = {
2134 .num_items = 4,
2135 .items = {
2136 { "Mic", 0x0 },
2137 { "Front Mic", 0x1 },
2138 { "Line", 0x2 },
2139 { "CD", 0x4 },
2140 },
2141};
2142
2143/* fixed 8-channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002144static struct hda_channel_mode alc880_sixstack_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002145 { 8, NULL },
2146};
2147
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002148static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002149 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002150 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002151 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002152 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002153 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2154 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002155 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2156 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002157 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002158 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002159 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2160 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2161 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2162 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2163 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2164 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2165 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2166 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002167 {
2168 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2169 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01002170 .info = alc_ch_mode_info,
2171 .get = alc_ch_mode_get,
2172 .put = alc_ch_mode_put,
Takashi Iwai16ded522005-06-10 19:58:24 +02002173 },
2174 { } /* end */
2175};
2176
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002177
2178/*
2179 * ALC880 W810 model
2180 *
2181 * W810 has rear IO for:
2182 * Front (DAC 02)
2183 * Surround (DAC 03)
2184 * Center/LFE (DAC 04)
2185 * Digital out (06)
2186 *
2187 * The system also has a pair of internal speakers, and a headphone jack.
2188 * These are both connected to Line2 on the codec, hence to DAC 02.
Kailang Yangea1fb292008-08-26 12:58:38 +02002189 *
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002190 * There is a variable resistor to control the speaker or headphone
2191 * volume. This is a hardware-only device without a software API.
2192 *
2193 * Plugging headphones in will disable the internal speakers. This is
2194 * implemented in hardware, not via the driver using jack sense. In
2195 * a similar fashion, plugging into the rear socket marked "front" will
2196 * disable both the speakers and headphones.
2197 *
2198 * For input, there's a microphone jack, and an "audio in" jack.
2199 * These may not do anything useful with this driver yet, because I
2200 * haven't setup any initialization verbs for these yet...
2201 */
2202
2203static hda_nid_t alc880_w810_dac_nids[3] = {
2204 /* front, rear/surround, clfe */
2205 0x02, 0x03, 0x04
2206};
2207
2208/* fixed 6 channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002209static struct hda_channel_mode alc880_w810_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002210 { 6, NULL }
2211};
2212
2213/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002214static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002215 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002216 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002217 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002218 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002219 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2220 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002221 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2222 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002223 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2224 { } /* end */
2225};
2226
2227
2228/*
2229 * Z710V model
2230 *
2231 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002232 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
2233 * Line = 0x1a
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002234 */
2235
2236static hda_nid_t alc880_z71v_dac_nids[1] = {
2237 0x02
2238};
2239#define ALC880_Z71V_HP_DAC 0x03
2240
2241/* fixed 2 channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002242static struct hda_channel_mode alc880_2_jack_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002243 { 2, NULL }
2244};
2245
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002246static struct snd_kcontrol_new alc880_z71v_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002247 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002248 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002249 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002250 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002251 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2252 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2253 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2254 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2255 { } /* end */
2256};
2257
2258
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002259/*
2260 * ALC880 F1734 model
2261 *
2262 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
2263 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
2264 */
2265
2266static hda_nid_t alc880_f1734_dac_nids[1] = {
2267 0x03
2268};
2269#define ALC880_F1734_HP_DAC 0x02
2270
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002271static struct snd_kcontrol_new alc880_f1734_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002272 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002273 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01002274 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2275 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002276 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2277 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Takashi Iwai937b4162008-02-11 14:52:36 +01002278 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2279 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002280 { } /* end */
2281};
2282
Takashi Iwai937b4162008-02-11 14:52:36 +01002283static struct hda_input_mux alc880_f1734_capture_source = {
2284 .num_items = 2,
2285 .items = {
2286 { "Mic", 0x1 },
2287 { "CD", 0x4 },
2288 },
2289};
2290
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002291
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002292/*
2293 * ALC880 ASUS model
2294 *
2295 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
2296 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
2297 * Mic = 0x18, Line = 0x1a
2298 */
2299
2300#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
2301#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
2302
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002303static struct snd_kcontrol_new alc880_asus_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002304 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002305 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002306 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002307 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002308 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2309 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002310 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2311 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002312 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2313 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2314 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2315 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2316 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2317 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002318 {
2319 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2320 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01002321 .info = alc_ch_mode_info,
2322 .get = alc_ch_mode_get,
2323 .put = alc_ch_mode_put,
Takashi Iwai16ded522005-06-10 19:58:24 +02002324 },
2325 { } /* end */
2326};
2327
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002328/*
2329 * ALC880 ASUS W1V model
2330 *
2331 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
2332 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
2333 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
2334 */
2335
2336/* additional mixers to alc880_asus_mixer */
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01002337static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002338 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
2339 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002340 { } /* end */
2341};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002342
Kailang Yangdf694da2005-12-05 19:42:22 +01002343/* TCL S700 */
2344static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
2345 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2346 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2347 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
2348 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
2349 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
2350 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
2351 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
2352 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
2353 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01002354 { } /* end */
2355};
2356
Kailang Yangccc656c2006-10-17 12:32:26 +02002357/* Uniwill */
2358static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002359 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2360 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2361 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2362 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002363 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2364 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2365 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2366 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2367 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2368 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2369 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2370 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2371 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2372 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2373 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2374 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002375 {
2376 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2377 .name = "Channel Mode",
2378 .info = alc_ch_mode_info,
2379 .get = alc_ch_mode_get,
2380 .put = alc_ch_mode_put,
2381 },
2382 { } /* end */
2383};
2384
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01002385static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
2386 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2387 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2388 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2389 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
2390 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2391 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2392 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2393 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2394 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2395 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
2396 { } /* end */
2397};
2398
Kailang Yangccc656c2006-10-17 12:32:26 +02002399static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002400 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2401 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2402 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2403 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002404 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2405 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2406 { } /* end */
2407};
2408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01002410 * virtual master controls
2411 */
2412
2413/*
2414 * slave controls for virtual master
2415 */
2416static const char *alc_slave_vols[] = {
2417 "Front Playback Volume",
2418 "Surround Playback Volume",
2419 "Center Playback Volume",
2420 "LFE Playback Volume",
2421 "Side Playback Volume",
2422 "Headphone Playback Volume",
2423 "Speaker Playback Volume",
2424 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002425 "Line-Out Playback Volume",
Takashi Iwai26f5df22008-11-03 17:39:46 +01002426 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002427 NULL,
2428};
2429
2430static const char *alc_slave_sws[] = {
2431 "Front Playback Switch",
2432 "Surround Playback Switch",
2433 "Center Playback Switch",
2434 "LFE Playback Switch",
2435 "Side Playback Switch",
2436 "Headphone Playback Switch",
2437 "Speaker Playback Switch",
2438 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01002439 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01002440 "Line-Out Playback Switch",
2441 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002442 NULL,
2443};
2444
2445/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002446 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 */
Takashi Iwai603c4012008-07-30 15:01:44 +02002448
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002449#define NID_MAPPING (-1)
2450
2451#define SUBDEV_SPEAKER_ (0 << 6)
2452#define SUBDEV_HP_ (1 << 6)
2453#define SUBDEV_LINE_ (2 << 6)
2454#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
2455#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
2456#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
2457
Takashi Iwai603c4012008-07-30 15:01:44 +02002458static void alc_free_kctls(struct hda_codec *codec);
2459
Takashi Iwai67d634c2009-11-16 15:35:59 +01002460#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002461/* additional beep mixers; the actual parameters are overwritten at build */
2462static struct snd_kcontrol_new alc_beep_mixer[] = {
2463 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002464 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002465 { } /* end */
2466};
Takashi Iwai67d634c2009-11-16 15:35:59 +01002467#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002468
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469static int alc_build_controls(struct hda_codec *codec)
2470{
2471 struct alc_spec *spec = codec->spec;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002472 struct snd_kcontrol *kctl;
2473 struct snd_kcontrol_new *knew;
2474 int i, j, err;
2475 unsigned int u;
2476 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
2478 for (i = 0; i < spec->num_mixers; i++) {
2479 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
2480 if (err < 0)
2481 return err;
2482 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002483 if (spec->cap_mixer) {
2484 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
2485 if (err < 0)
2486 return err;
2487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002489 err = snd_hda_create_spdif_out_ctls(codec,
2490 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 if (err < 0)
2492 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002493 if (!spec->no_analog) {
2494 err = snd_hda_create_spdif_share_sw(codec,
2495 &spec->multiout);
2496 if (err < 0)
2497 return err;
2498 spec->multiout.share_spdif = 1;
2499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 }
2501 if (spec->dig_in_nid) {
2502 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
2503 if (err < 0)
2504 return err;
2505 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01002506
Takashi Iwai67d634c2009-11-16 15:35:59 +01002507#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002508 /* create beep controls if needed */
2509 if (spec->beep_amp) {
2510 struct snd_kcontrol_new *knew;
2511 for (knew = alc_beep_mixer; knew->name; knew++) {
2512 struct snd_kcontrol *kctl;
2513 kctl = snd_ctl_new1(knew, codec);
2514 if (!kctl)
2515 return -ENOMEM;
2516 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002517 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002518 if (err < 0)
2519 return err;
2520 }
2521 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01002522#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002523
Takashi Iwai2134ea42008-01-10 16:53:55 +01002524 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002525 if (!spec->no_analog &&
2526 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002527 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01002528 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002529 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01002530 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002531 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01002532 if (err < 0)
2533 return err;
2534 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002535 if (!spec->no_analog &&
2536 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002537 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
2538 NULL, alc_slave_sws);
2539 if (err < 0)
2540 return err;
2541 }
2542
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002543 /* assign Capture Source enums to NID */
2544 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
2545 if (!kctl)
2546 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
2547 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwaid1409ae2009-12-17 15:01:31 +01002548 hda_nid_t *nids = spec->capsrc_nids;
2549 if (!nids)
2550 nids = spec->adc_nids;
Takashi Iwai21949f02009-12-23 08:31:59 +01002551 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002552 if (err < 0)
2553 return err;
2554 }
2555 if (spec->cap_mixer) {
2556 const char *kname = kctl ? kctl->id.name : NULL;
2557 for (knew = spec->cap_mixer; knew->name; knew++) {
2558 if (kname && strcmp(knew->name, kname) == 0)
2559 continue;
2560 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
2561 for (i = 0; kctl && i < kctl->count; i++) {
2562 err = snd_hda_add_nid(codec, kctl, i,
2563 spec->adc_nids[i]);
2564 if (err < 0)
2565 return err;
2566 }
2567 }
2568 }
2569
2570 /* other nid->control mapping */
2571 for (i = 0; i < spec->num_mixers; i++) {
2572 for (knew = spec->mixers[i]; knew->name; knew++) {
2573 if (knew->iface != NID_MAPPING)
2574 continue;
2575 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
2576 if (kctl == NULL)
2577 continue;
2578 u = knew->subdevice;
2579 for (j = 0; j < 4; j++, u >>= 8) {
2580 nid = u & 0x3f;
2581 if (nid == 0)
2582 continue;
2583 switch (u & 0xc0) {
2584 case SUBDEV_SPEAKER_:
2585 nid = spec->autocfg.speaker_pins[nid];
2586 break;
2587 case SUBDEV_LINE_:
2588 nid = spec->autocfg.line_out_pins[nid];
2589 break;
2590 case SUBDEV_HP_:
2591 nid = spec->autocfg.hp_pins[nid];
2592 break;
2593 default:
2594 continue;
2595 }
2596 err = snd_hda_add_nid(codec, kctl, 0, nid);
2597 if (err < 0)
2598 return err;
2599 }
2600 u = knew->private_value;
2601 for (j = 0; j < 4; j++, u >>= 8) {
2602 nid = u & 0xff;
2603 if (nid == 0)
2604 continue;
2605 err = snd_hda_add_nid(codec, kctl, 0, nid);
2606 if (err < 0)
2607 return err;
2608 }
2609 }
2610 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01002611
2612 alc_free_kctls(codec); /* no longer needed */
2613
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 return 0;
2615}
2616
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002617
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618/*
2619 * initialize the codec volumes, etc
2620 */
2621
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002622/*
2623 * generic initialization of ADC, input mixers and output mixers
2624 */
2625static struct hda_verb alc880_volume_init_verbs[] = {
2626 /*
2627 * Unmute ADC0-2 and set the default input to mic-in
2628 */
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002629 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002630 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002631 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002632 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002633 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002634 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002636 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2637 * mixer widget
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002638 * Note: PASD motherboards uses the Line In 2 as the input for front
2639 * panel mic (mic 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002641 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02002642 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2643 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2644 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2645 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2646 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2647 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2648 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002650 /*
2651 * Set up output mixers (0x0c - 0x0f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002653 /* set vol=0 to output mixers */
2654 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2655 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2656 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2657 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2658 /* set up input amps for analog loopback */
2659 /* Amp Indices: DAC = 0, mixer = 1 */
Takashi Iwai05acb862005-06-10 19:50:25 +02002660 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2661 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002662 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2663 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002664 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2665 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002666 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2667 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
2669 { }
2670};
2671
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002672/*
2673 * 3-stack pin configuration:
2674 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
2675 */
2676static struct hda_verb alc880_pin_3stack_init_verbs[] = {
2677 /*
2678 * preset connection lists of input pins
2679 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
2680 */
2681 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
2682 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2683 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
2684
2685 /*
2686 * Set pin mode and muting
2687 */
2688 /* set front pin widgets 0x14 for output */
2689 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2690 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2691 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2692 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2693 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2694 /* Mic2 (as headphone out) for HP output */
2695 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2696 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2697 /* Line In pin widget for input */
2698 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2699 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2700 /* Line2 (as front mic) pin widget for input and vref at 80% */
2701 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2702 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2703 /* CD pin widget for input */
2704 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2705
2706 { }
2707};
2708
2709/*
2710 * 5-stack pin configuration:
2711 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
2712 * line-in/side = 0x1a, f-mic = 0x1b
2713 */
2714static struct hda_verb alc880_pin_5stack_init_verbs[] = {
2715 /*
2716 * preset connection lists of input pins
2717 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
2718 */
2719 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2720 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
2721
2722 /*
2723 * Set pin mode and muting
2724 */
2725 /* set pin widgets 0x14-0x17 for output */
Takashi Iwai05acb862005-06-10 19:50:25 +02002726 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2727 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2728 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2729 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002730 /* unmute pins for output (no gain on this amp) */
2731 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2732 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2733 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2734 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2735
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 /* Mic1 (rear panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02002737 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002738 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2739 /* Mic2 (as headphone out) for HP output */
2740 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai05acb862005-06-10 19:50:25 +02002741 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002742 /* Line In pin widget for input */
2743 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2744 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2745 /* Line2 (as front mic) pin widget for input and vref at 80% */
2746 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2747 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2748 /* CD pin widget for input */
2749 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
2751 { }
2752};
2753
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002754/*
2755 * W810 pin configuration:
2756 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
2757 */
2758static struct hda_verb alc880_pin_w810_init_verbs[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 /* hphone/speaker input selector: front DAC */
2760 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
2761
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002762 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2763 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2764 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2765 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2766 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2767 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2768
2769 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai05acb862005-06-10 19:50:25 +02002770 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 { }
2773};
2774
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002775/*
2776 * Z71V pin configuration:
2777 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
2778 */
2779static struct hda_verb alc880_pin_z71v_init_verbs[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02002780 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002781 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai05acb862005-06-10 19:50:25 +02002782 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002783 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002784
Takashi Iwai16ded522005-06-10 19:58:24 +02002785 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002786 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai16ded522005-06-10 19:58:24 +02002787 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002788 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002789
2790 { }
2791};
2792
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002793/*
2794 * 6-stack pin configuration:
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002795 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
2796 * f-mic = 0x19, line = 0x1a, HP = 0x1b
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002797 */
2798static struct hda_verb alc880_pin_6stack_init_verbs[] = {
2799 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2800
Takashi Iwai16ded522005-06-10 19:58:24 +02002801 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002802 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002803 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002804 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002805 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002806 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002807 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002808 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2809
Takashi Iwai16ded522005-06-10 19:58:24 +02002810 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002811 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002812 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002813 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002814 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002815 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002816 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai16ded522005-06-10 19:58:24 +02002817 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002818 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yangea1fb292008-08-26 12:58:38 +02002819
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002820 { }
2821};
Takashi Iwai16ded522005-06-10 19:58:24 +02002822
Kailang Yangccc656c2006-10-17 12:32:26 +02002823/*
2824 * Uniwill pin configuration:
2825 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
2826 * line = 0x1a
2827 */
2828static struct hda_verb alc880_uniwill_init_verbs[] = {
2829 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2830
2831 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2832 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2833 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2834 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2835 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2836 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2837 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2838 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2839 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2840 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2841 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2842 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2843 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2844 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2845
2846 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2847 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2848 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2849 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2850 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2851 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2852 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
2853 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
2854 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2855
2856 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
2857 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
2858
2859 { }
2860};
2861
2862/*
2863* Uniwill P53
Kailang Yangea1fb292008-08-26 12:58:38 +02002864* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
Kailang Yangccc656c2006-10-17 12:32:26 +02002865 */
2866static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
2867 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2868
2869 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2870 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2871 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2872 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2873 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2874 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2875 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2876 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2877 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2878 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2879 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2880 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2881
2882 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2883 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2884 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2885 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2886 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2887 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2888
2889 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
2890 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
2891
2892 { }
2893};
2894
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01002895static struct hda_verb alc880_beep_init_verbs[] = {
2896 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
2897 { }
2898};
2899
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002900/* auto-toggle front mic */
2901static void alc880_uniwill_mic_automute(struct hda_codec *codec)
2902{
2903 unsigned int present;
2904 unsigned char bits;
Kailang Yangccc656c2006-10-17 12:32:26 +02002905
Wu Fengguang864f92b2009-11-18 12:38:02 +08002906 present = snd_hda_jack_detect(codec, 0x18);
Takashi Iwai47fd8302007-08-10 17:11:07 +02002907 bits = present ? HDA_AMP_MUTE : 0;
2908 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002909}
2910
Takashi Iwai4f5d17062009-08-11 18:17:46 +02002911static void alc880_uniwill_setup(struct hda_codec *codec)
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002912{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002913 struct alc_spec *spec = codec->spec;
2914
2915 spec->autocfg.hp_pins[0] = 0x14;
2916 spec->autocfg.speaker_pins[0] = 0x15;
2917 spec->autocfg.speaker_pins[0] = 0x16;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02002918}
2919
2920static void alc880_uniwill_init_hook(struct hda_codec *codec)
2921{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002922 alc_automute_amp(codec);
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002923 alc880_uniwill_mic_automute(codec);
Kailang Yangccc656c2006-10-17 12:32:26 +02002924}
2925
2926static void alc880_uniwill_unsol_event(struct hda_codec *codec,
2927 unsigned int res)
2928{
2929 /* Looks like the unsol event is incompatible with the standard
2930 * definition. 4bit tag is placed at 28 bit!
2931 */
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002932 switch (res >> 28) {
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002933 case ALC880_MIC_EVENT:
2934 alc880_uniwill_mic_automute(codec);
2935 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002936 default:
2937 alc_automute_amp_unsol_event(codec, res);
2938 break;
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002939 }
Kailang Yangccc656c2006-10-17 12:32:26 +02002940}
2941
Takashi Iwai4f5d17062009-08-11 18:17:46 +02002942static void alc880_uniwill_p53_setup(struct hda_codec *codec)
Kailang Yangccc656c2006-10-17 12:32:26 +02002943{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002944 struct alc_spec *spec = codec->spec;
Kailang Yangccc656c2006-10-17 12:32:26 +02002945
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002946 spec->autocfg.hp_pins[0] = 0x14;
2947 spec->autocfg.speaker_pins[0] = 0x15;
Kailang Yangccc656c2006-10-17 12:32:26 +02002948}
2949
2950static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
2951{
2952 unsigned int present;
Kailang Yangea1fb292008-08-26 12:58:38 +02002953
Kailang Yangccc656c2006-10-17 12:32:26 +02002954 present = snd_hda_codec_read(codec, 0x21, 0,
Takashi Iwai47fd8302007-08-10 17:11:07 +02002955 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
2956 present &= HDA_AMP_VOLMASK;
2957 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
2958 HDA_AMP_VOLMASK, present);
2959 snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
2960 HDA_AMP_VOLMASK, present);
Kailang Yangccc656c2006-10-17 12:32:26 +02002961}
Takashi Iwai47fd8302007-08-10 17:11:07 +02002962
Kailang Yangccc656c2006-10-17 12:32:26 +02002963static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
2964 unsigned int res)
2965{
2966 /* Looks like the unsol event is incompatible with the standard
2967 * definition. 4bit tag is placed at 28 bit!
2968 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002969 if ((res >> 28) == ALC880_DCVOL_EVENT)
Kailang Yangccc656c2006-10-17 12:32:26 +02002970 alc880_uniwill_p53_dcvol_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002971 else
2972 alc_automute_amp_unsol_event(codec, res);
Kailang Yangccc656c2006-10-17 12:32:26 +02002973}
2974
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002975/*
2976 * F1734 pin configuration:
2977 * HP = 0x14, speaker-out = 0x15, mic = 0x18
2978 */
2979static struct hda_verb alc880_pin_f1734_init_verbs[] = {
Michael Gruberee7a9c72008-03-10 11:30:59 +01002980 {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002981 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
2982 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
2983 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
2984 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
2985
2986 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2987 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2988 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2989 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2990
2991 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2992 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Michael Gruberee7a9c72008-03-10 11:30:59 +01002993 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002994 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2995 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2996 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2997 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2998 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2999 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai16ded522005-06-10 19:58:24 +02003000
Takashi Iwai937b4162008-02-11 14:52:36 +01003001 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
3002 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
3003
Takashi Iwai16ded522005-06-10 19:58:24 +02003004 { }
3005};
3006
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003007/*
3008 * ASUS pin configuration:
3009 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
3010 */
3011static struct hda_verb alc880_pin_asus_init_verbs[] = {
3012 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
3013 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
3014 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
3015 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
3016
3017 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3018 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3019 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3020 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3021 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3022 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3023 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3024 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3025
3026 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3027 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3028 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3029 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3030 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3031 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3032 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3033 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3034 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yangea1fb292008-08-26 12:58:38 +02003035
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003036 { }
3037};
3038
3039/* Enable GPIO mask and set output */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003040#define alc880_gpio1_init_verbs alc_gpio1_init_verbs
3041#define alc880_gpio2_init_verbs alc_gpio2_init_verbs
David Heidelberger64a8be72009-06-08 16:15:18 +02003042#define alc880_gpio3_init_verbs alc_gpio3_init_verbs
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003043
Kailang Yangdf694da2005-12-05 19:42:22 +01003044/* Clevo m520g init */
3045static struct hda_verb alc880_pin_clevo_init_verbs[] = {
3046 /* headphone output */
3047 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3048 /* line-out */
3049 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3050 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3051 /* Line-in */
3052 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3053 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3054 /* CD */
3055 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3056 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3057 /* Mic1 (rear panel) */
3058 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3059 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3060 /* Mic2 (front panel) */
3061 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3062 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3063 /* headphone */
3064 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3065 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3066 /* change to EAPD mode */
3067 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3068 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3069
3070 { }
3071};
3072
3073static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
Takashi Iwai4b146cb2006-07-28 14:42:36 +02003074 /* change to EAPD mode */
3075 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3076 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3077
Kailang Yangdf694da2005-12-05 19:42:22 +01003078 /* Headphone output */
3079 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3080 /* Front output*/
3081 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3082 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3083
3084 /* Line In pin widget for input */
3085 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3086 /* CD pin widget for input */
3087 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3088 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3089 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3090
3091 /* change to EAPD mode */
3092 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3093 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
3094
3095 { }
3096};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003097
3098/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003099 * LG m1 express dual
3100 *
3101 * Pin assignment:
3102 * Rear Line-In/Out (blue): 0x14
3103 * Build-in Mic-In: 0x15
3104 * Speaker-out: 0x17
3105 * HP-Out (green): 0x1b
3106 * Mic-In/Out (red): 0x19
3107 * SPDIF-Out: 0x1e
3108 */
3109
3110/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
3111static hda_nid_t alc880_lg_dac_nids[3] = {
3112 0x05, 0x02, 0x03
3113};
3114
3115/* seems analog CD is not working */
3116static struct hda_input_mux alc880_lg_capture_source = {
3117 .num_items = 3,
3118 .items = {
3119 { "Mic", 0x1 },
3120 { "Line", 0x5 },
3121 { "Internal Mic", 0x6 },
3122 },
3123};
3124
3125/* 2,4,6 channel modes */
3126static struct hda_verb alc880_lg_ch2_init[] = {
3127 /* set line-in and mic-in to input */
3128 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
3129 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3130 { }
3131};
3132
3133static struct hda_verb alc880_lg_ch4_init[] = {
3134 /* set line-in to out and mic-in to input */
3135 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3136 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3137 { }
3138};
3139
3140static struct hda_verb alc880_lg_ch6_init[] = {
3141 /* set line-in and mic-in to output */
3142 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3143 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3144 { }
3145};
3146
3147static struct hda_channel_mode alc880_lg_ch_modes[3] = {
3148 { 2, alc880_lg_ch2_init },
3149 { 4, alc880_lg_ch4_init },
3150 { 6, alc880_lg_ch6_init },
3151};
3152
3153static struct snd_kcontrol_new alc880_lg_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01003154 HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3155 HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003156 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3157 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
3158 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
3159 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
3160 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
3161 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
3162 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3163 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3164 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
3165 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
3166 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
3167 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
3168 {
3169 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3170 .name = "Channel Mode",
3171 .info = alc_ch_mode_info,
3172 .get = alc_ch_mode_get,
3173 .put = alc_ch_mode_put,
3174 },
3175 { } /* end */
3176};
3177
3178static struct hda_verb alc880_lg_init_verbs[] = {
3179 /* set capture source to mic-in */
3180 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3181 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3182 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3183 /* mute all amp mixer inputs */
3184 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
Takashi Iwaicb53c622007-08-10 17:21:45 +02003185 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3186 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003187 /* line-in to input */
3188 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3189 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3190 /* built-in mic */
3191 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3192 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3193 /* speaker-out */
3194 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3195 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3196 /* mic-in to input */
3197 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3198 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3199 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3200 /* HP-out */
3201 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
3202 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3203 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3204 /* jack sense */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003205 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003206 { }
3207};
3208
3209/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003210static void alc880_lg_setup(struct hda_codec *codec)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003211{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003212 struct alc_spec *spec = codec->spec;
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003213
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003214 spec->autocfg.hp_pins[0] = 0x1b;
3215 spec->autocfg.speaker_pins[0] = 0x17;
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003216}
3217
3218/*
Takashi Iwaid6815182006-03-23 16:06:23 +01003219 * LG LW20
3220 *
3221 * Pin assignment:
3222 * Speaker-out: 0x14
3223 * Mic-In: 0x18
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003224 * Built-in Mic-In: 0x19
3225 * Line-In: 0x1b
3226 * HP-Out: 0x1a
Takashi Iwaid6815182006-03-23 16:06:23 +01003227 * SPDIF-Out: 0x1e
3228 */
3229
Takashi Iwaid6815182006-03-23 16:06:23 +01003230static struct hda_input_mux alc880_lg_lw_capture_source = {
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003231 .num_items = 3,
Takashi Iwaid6815182006-03-23 16:06:23 +01003232 .items = {
3233 { "Mic", 0x0 },
3234 { "Internal Mic", 0x1 },
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003235 { "Line In", 0x2 },
Takashi Iwaid6815182006-03-23 16:06:23 +01003236 },
3237};
3238
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003239#define alc880_lg_lw_modes alc880_threestack_modes
3240
Takashi Iwaid6815182006-03-23 16:06:23 +01003241static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003242 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3243 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3244 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3245 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
3246 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3247 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3248 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3249 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3250 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3251 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwaid6815182006-03-23 16:06:23 +01003252 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3253 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3254 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
3255 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003256 {
3257 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3258 .name = "Channel Mode",
3259 .info = alc_ch_mode_info,
3260 .get = alc_ch_mode_get,
3261 .put = alc_ch_mode_put,
3262 },
Takashi Iwaid6815182006-03-23 16:06:23 +01003263 { } /* end */
3264};
3265
3266static struct hda_verb alc880_lg_lw_init_verbs[] = {
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003267 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3268 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
3269 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
3270
Takashi Iwaid6815182006-03-23 16:06:23 +01003271 /* set capture source to mic-in */
3272 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3273 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3274 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwaicb53c622007-08-10 17:21:45 +02003275 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Takashi Iwaid6815182006-03-23 16:06:23 +01003276 /* speaker-out */
3277 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3278 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3279 /* HP-out */
Takashi Iwaid6815182006-03-23 16:06:23 +01003280 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3281 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3282 /* mic-in to input */
3283 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3284 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3285 /* built-in mic */
3286 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3287 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3288 /* jack sense */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003289 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaid6815182006-03-23 16:06:23 +01003290 { }
3291};
3292
3293/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003294static void alc880_lg_lw_setup(struct hda_codec *codec)
Takashi Iwaid6815182006-03-23 16:06:23 +01003295{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003296 struct alc_spec *spec = codec->spec;
Takashi Iwaid6815182006-03-23 16:06:23 +01003297
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003298 spec->autocfg.hp_pins[0] = 0x1b;
3299 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwaid6815182006-03-23 16:06:23 +01003300}
3301
Takashi Iwaidf99cd32008-04-25 15:25:04 +02003302static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
3303 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3304 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
3305 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3306 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3307 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3308 HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
3309 { } /* end */
3310};
3311
3312static struct hda_input_mux alc880_medion_rim_capture_source = {
3313 .num_items = 2,
3314 .items = {
3315 { "Mic", 0x0 },
3316 { "Internal Mic", 0x1 },
3317 },
3318};
3319
3320static struct hda_verb alc880_medion_rim_init_verbs[] = {
3321 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3322
3323 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3324 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3325
3326 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3327 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3328 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3329 /* Mic2 (as headphone out) for HP output */
3330 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3331 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3332 /* Internal Speaker */
3333 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3334 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3335
3336 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3337 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3338
3339 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3340 { }
3341};
3342
3343/* toggle speaker-output according to the hp-jack state */
3344static void alc880_medion_rim_automute(struct hda_codec *codec)
3345{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003346 struct alc_spec *spec = codec->spec;
3347 alc_automute_amp(codec);
3348 /* toggle EAPD */
3349 if (spec->jack_present)
Takashi Iwaidf99cd32008-04-25 15:25:04 +02003350 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
3351 else
3352 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
3353}
3354
3355static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
3356 unsigned int res)
3357{
3358 /* Looks like the unsol event is incompatible with the standard
3359 * definition. 4bit tag is placed at 28 bit!
3360 */
3361 if ((res >> 28) == ALC880_HP_EVENT)
3362 alc880_medion_rim_automute(codec);
3363}
3364
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003365static void alc880_medion_rim_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003366{
3367 struct alc_spec *spec = codec->spec;
3368
3369 spec->autocfg.hp_pins[0] = 0x14;
3370 spec->autocfg.speaker_pins[0] = 0x1b;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003371}
3372
Takashi Iwaicb53c622007-08-10 17:21:45 +02003373#ifdef CONFIG_SND_HDA_POWER_SAVE
3374static struct hda_amp_list alc880_loopbacks[] = {
3375 { 0x0b, HDA_INPUT, 0 },
3376 { 0x0b, HDA_INPUT, 1 },
3377 { 0x0b, HDA_INPUT, 2 },
3378 { 0x0b, HDA_INPUT, 3 },
3379 { 0x0b, HDA_INPUT, 4 },
3380 { } /* end */
3381};
3382
3383static struct hda_amp_list alc880_lg_loopbacks[] = {
3384 { 0x0b, HDA_INPUT, 1 },
3385 { 0x0b, HDA_INPUT, 6 },
3386 { 0x0b, HDA_INPUT, 7 },
3387 { } /* end */
3388};
3389#endif
3390
Takashi Iwaid6815182006-03-23 16:06:23 +01003391/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003392 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003393 */
Takashi Iwai16ded522005-06-10 19:58:24 +02003394
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395static int alc_init(struct hda_codec *codec)
3396{
3397 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003398 unsigned int i;
3399
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02003400 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02003401 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02003402
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003403 for (i = 0; i < spec->num_init_verbs; i++)
3404 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003405
3406 if (spec->init_hook)
3407 spec->init_hook(codec);
3408
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 return 0;
3410}
3411
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003412static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
3413{
3414 struct alc_spec *spec = codec->spec;
3415
3416 if (spec->unsol_event)
3417 spec->unsol_event(codec, res);
3418}
3419
Takashi Iwaicb53c622007-08-10 17:21:45 +02003420#ifdef CONFIG_SND_HDA_POWER_SAVE
3421static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
3422{
3423 struct alc_spec *spec = codec->spec;
3424 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
3425}
3426#endif
3427
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428/*
3429 * Analog playback callbacks
3430 */
3431static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
3432 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003433 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434{
3435 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01003436 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
3437 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438}
3439
3440static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3441 struct hda_codec *codec,
3442 unsigned int stream_tag,
3443 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003444 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445{
3446 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003447 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3448 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449}
3450
3451static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3452 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003453 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454{
3455 struct alc_spec *spec = codec->spec;
3456 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3457}
3458
3459/*
3460 * Digital out
3461 */
3462static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3463 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003464 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465{
3466 struct alc_spec *spec = codec->spec;
3467 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3468}
3469
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003470static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3471 struct hda_codec *codec,
3472 unsigned int stream_tag,
3473 unsigned int format,
3474 struct snd_pcm_substream *substream)
3475{
3476 struct alc_spec *spec = codec->spec;
3477 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3478 stream_tag, format, substream);
3479}
3480
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01003481static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3482 struct hda_codec *codec,
3483 struct snd_pcm_substream *substream)
3484{
3485 struct alc_spec *spec = codec->spec;
3486 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
3487}
3488
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
3490 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003491 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492{
3493 struct alc_spec *spec = codec->spec;
3494 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
3495}
3496
3497/*
3498 * Analog capture
3499 */
Takashi Iwai63300792008-01-24 15:31:36 +01003500static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 struct hda_codec *codec,
3502 unsigned int stream_tag,
3503 unsigned int format,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003504 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505{
3506 struct alc_spec *spec = codec->spec;
3507
Takashi Iwai63300792008-01-24 15:31:36 +01003508 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 stream_tag, 0, format);
3510 return 0;
3511}
3512
Takashi Iwai63300792008-01-24 15:31:36 +01003513static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 struct hda_codec *codec,
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003515 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516{
3517 struct alc_spec *spec = codec->spec;
3518
Takashi Iwai888afa12008-03-18 09:57:50 +01003519 snd_hda_codec_cleanup_stream(codec,
3520 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 return 0;
3522}
3523
3524
3525/*
3526 */
3527static struct hda_pcm_stream alc880_pcm_analog_playback = {
3528 .substreams = 1,
3529 .channels_min = 2,
3530 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003531 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532 .ops = {
3533 .open = alc880_playback_pcm_open,
3534 .prepare = alc880_playback_pcm_prepare,
3535 .cleanup = alc880_playback_pcm_cleanup
3536 },
3537};
3538
3539static struct hda_pcm_stream alc880_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01003540 .substreams = 1,
3541 .channels_min = 2,
3542 .channels_max = 2,
3543 /* NID is set in alc_build_pcms */
3544};
3545
3546static struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
3547 .substreams = 1,
3548 .channels_min = 2,
3549 .channels_max = 2,
3550 /* NID is set in alc_build_pcms */
3551};
3552
3553static struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
3554 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 .channels_min = 2,
3556 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003557 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 .ops = {
Takashi Iwai63300792008-01-24 15:31:36 +01003559 .prepare = alc880_alt_capture_pcm_prepare,
3560 .cleanup = alc880_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561 },
3562};
3563
3564static struct hda_pcm_stream alc880_pcm_digital_playback = {
3565 .substreams = 1,
3566 .channels_min = 2,
3567 .channels_max = 2,
3568 /* NID is set in alc_build_pcms */
3569 .ops = {
3570 .open = alc880_dig_playback_pcm_open,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003571 .close = alc880_dig_playback_pcm_close,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01003572 .prepare = alc880_dig_playback_pcm_prepare,
3573 .cleanup = alc880_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 },
3575};
3576
3577static struct hda_pcm_stream alc880_pcm_digital_capture = {
3578 .substreams = 1,
3579 .channels_min = 2,
3580 .channels_max = 2,
3581 /* NID is set in alc_build_pcms */
3582};
3583
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01003584/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwai63300792008-01-24 15:31:36 +01003585static struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01003586 .substreams = 0,
3587 .channels_min = 0,
3588 .channels_max = 0,
3589};
3590
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591static int alc_build_pcms(struct hda_codec *codec)
3592{
3593 struct alc_spec *spec = codec->spec;
3594 struct hda_pcm *info = spec->pcm_rec;
3595 int i;
3596
3597 codec->num_pcms = 1;
3598 codec->pcm_info = info;
3599
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003600 if (spec->no_analog)
3601 goto skip_analog;
3602
Takashi Iwai812a2cc2009-05-16 10:00:49 +02003603 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
3604 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01003606
Takashi Iwai4a471b72005-12-07 13:56:29 +01003607 if (spec->stream_analog_playback) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003608 if (snd_BUG_ON(!spec->multiout.dac_nids))
3609 return -EINVAL;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003610 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
3611 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
3612 }
3613 if (spec->stream_analog_capture) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003614 if (snd_BUG_ON(!spec->adc_nids))
3615 return -EINVAL;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003616 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
3617 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
3618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619
Takashi Iwai4a471b72005-12-07 13:56:29 +01003620 if (spec->channel_mode) {
3621 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
3622 for (i = 0; i < spec->num_channel_mode; i++) {
3623 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
3624 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
3625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 }
3627 }
3628
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003629 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02003630 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02003632 snprintf(spec->stream_name_digital,
3633 sizeof(spec->stream_name_digital),
3634 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02003635 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08003636 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02003637 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01003639 if (spec->dig_out_type)
3640 info->pcm_type = spec->dig_out_type;
3641 else
3642 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003643 if (spec->multiout.dig_out_nid &&
3644 spec->stream_digital_playback) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
3646 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
3647 }
Takashi Iwai4a471b72005-12-07 13:56:29 +01003648 if (spec->dig_in_nid &&
3649 spec->stream_digital_capture) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
3651 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
3652 }
Takashi Iwai963f8032008-08-11 10:04:40 +02003653 /* FIXME: do we need this for all Realtek codec models? */
3654 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655 }
3656
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003657 if (spec->no_analog)
3658 return 0;
3659
Takashi Iwaie08a0072006-09-07 17:52:14 +02003660 /* If the use of more than one ADC is requested for the current
3661 * model, configure a second analog capture-only PCM.
3662 */
3663 /* Additional Analaog capture for index #2 */
Takashi Iwai63300792008-01-24 15:31:36 +01003664 if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||
3665 (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02003666 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02003667 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02003668 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01003669 if (spec->alt_dac_nid) {
3670 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3671 *spec->stream_analog_alt_playback;
3672 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
3673 spec->alt_dac_nid;
3674 } else {
3675 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3676 alc_pcm_null_stream;
3677 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
3678 }
3679 if (spec->num_adc_nids > 1) {
3680 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3681 *spec->stream_analog_alt_capture;
3682 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
3683 spec->adc_nids[1];
3684 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
3685 spec->num_adc_nids - 1;
3686 } else {
3687 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3688 alc_pcm_null_stream;
3689 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02003690 }
3691 }
3692
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 return 0;
3694}
3695
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003696static inline void alc_shutup(struct hda_codec *codec)
3697{
3698 snd_hda_shutup_pins(codec);
3699}
3700
Takashi Iwai603c4012008-07-30 15:01:44 +02003701static void alc_free_kctls(struct hda_codec *codec)
3702{
3703 struct alc_spec *spec = codec->spec;
3704
3705 if (spec->kctls.list) {
3706 struct snd_kcontrol_new *kctl = spec->kctls.list;
3707 int i;
3708 for (i = 0; i < spec->kctls.used; i++)
3709 kfree(kctl[i].name);
3710 }
3711 snd_array_free(&spec->kctls);
3712}
3713
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714static void alc_free(struct hda_codec *codec)
3715{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003716 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003717
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02003718 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003719 return;
3720
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003721 alc_shutup(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02003722 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003723 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09003724 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725}
3726
Hector Martinf5de24b2009-12-20 22:51:31 +01003727#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05003728static void alc_power_eapd(struct hda_codec *codec)
3729{
3730 /* We currently only handle front, HP */
3731 switch (codec->vendor_id) {
3732 case 0x10ec0260:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003733 set_eapd(codec, 0x0f, 0);
3734 set_eapd(codec, 0x10, 0);
Daniel T Chenc97259d2009-12-27 18:52:08 -05003735 break;
3736 case 0x10ec0262:
3737 case 0x10ec0267:
3738 case 0x10ec0268:
3739 case 0x10ec0269:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003740 case 0x10ec0270:
Daniel T Chenc97259d2009-12-27 18:52:08 -05003741 case 0x10ec0272:
3742 case 0x10ec0660:
3743 case 0x10ec0662:
3744 case 0x10ec0663:
3745 case 0x10ec0862:
3746 case 0x10ec0889:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003747 set_eapd(codec, 0x14, 0);
3748 set_eapd(codec, 0x15, 0);
Daniel T Chenc97259d2009-12-27 18:52:08 -05003749 break;
3750 }
3751}
3752
Hector Martinf5de24b2009-12-20 22:51:31 +01003753static int alc_suspend(struct hda_codec *codec, pm_message_t state)
3754{
3755 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003756 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01003757 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05003758 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01003759 return 0;
3760}
3761#endif
3762
Takashi Iwaie044c392008-10-27 16:56:24 +01003763#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaie044c392008-10-27 16:56:24 +01003764static int alc_resume(struct hda_codec *codec)
3765{
Takashi Iwaie044c392008-10-27 16:56:24 +01003766 codec->patch_ops.init(codec);
3767 snd_hda_codec_resume_amp(codec);
3768 snd_hda_codec_resume_cache(codec);
3769 return 0;
3770}
Takashi Iwaie044c392008-10-27 16:56:24 +01003771#endif
3772
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773/*
3774 */
3775static struct hda_codec_ops alc_patch_ops = {
3776 .build_controls = alc_build_controls,
3777 .build_pcms = alc_build_pcms,
3778 .init = alc_init,
3779 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003780 .unsol_event = alc_unsol_event,
Takashi Iwaie044c392008-10-27 16:56:24 +01003781#ifdef SND_HDA_NEEDS_RESUME
3782 .resume = alc_resume,
3783#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003784#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01003785 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02003786 .check_power_status = alc_check_power_status,
3787#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05003788 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789};
3790
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003791
3792/*
3793 * Test configuration for debugging
3794 *
3795 * Almost all inputs/outputs are enabled. I/O pins can be configured via
3796 * enum controls.
3797 */
3798#ifdef CONFIG_SND_DEBUG
3799static hda_nid_t alc880_test_dac_nids[4] = {
3800 0x02, 0x03, 0x04, 0x05
3801};
3802
3803static struct hda_input_mux alc880_test_capture_source = {
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003804 .num_items = 7,
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003805 .items = {
3806 { "In-1", 0x0 },
3807 { "In-2", 0x1 },
3808 { "In-3", 0x2 },
3809 { "In-4", 0x3 },
3810 { "CD", 0x4 },
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003811 { "Front", 0x5 },
3812 { "Surround", 0x6 },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003813 },
3814};
3815
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003816static struct hda_channel_mode alc880_test_modes[4] = {
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003817 { 2, NULL },
Takashi Iwaifd2c3262005-05-13 17:18:42 +02003818 { 4, NULL },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003819 { 6, NULL },
Takashi Iwaifd2c3262005-05-13 17:18:42 +02003820 { 8, NULL },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003821};
3822
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003823static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
3824 struct snd_ctl_elem_info *uinfo)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003825{
3826 static char *texts[] = {
3827 "N/A", "Line Out", "HP Out",
3828 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
3829 };
3830 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3831 uinfo->count = 1;
3832 uinfo->value.enumerated.items = 8;
3833 if (uinfo->value.enumerated.item >= 8)
3834 uinfo->value.enumerated.item = 7;
3835 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3836 return 0;
3837}
3838
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003839static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
3840 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003841{
3842 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3843 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
3844 unsigned int pin_ctl, item = 0;
3845
3846 pin_ctl = snd_hda_codec_read(codec, nid, 0,
3847 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3848 if (pin_ctl & AC_PINCTL_OUT_EN) {
3849 if (pin_ctl & AC_PINCTL_HP_EN)
3850 item = 2;
3851 else
3852 item = 1;
3853 } else if (pin_ctl & AC_PINCTL_IN_EN) {
3854 switch (pin_ctl & AC_PINCTL_VREFEN) {
3855 case AC_PINCTL_VREF_HIZ: item = 3; break;
3856 case AC_PINCTL_VREF_50: item = 4; break;
3857 case AC_PINCTL_VREF_GRD: item = 5; break;
3858 case AC_PINCTL_VREF_80: item = 6; break;
3859 case AC_PINCTL_VREF_100: item = 7; break;
3860 }
3861 }
3862 ucontrol->value.enumerated.item[0] = item;
3863 return 0;
3864}
3865
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003866static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
3867 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003868{
3869 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3870 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
3871 static unsigned int ctls[] = {
3872 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
3873 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
3874 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
3875 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
3876 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
3877 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
3878 };
3879 unsigned int old_ctl, new_ctl;
3880
3881 old_ctl = snd_hda_codec_read(codec, nid, 0,
3882 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3883 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
3884 if (old_ctl != new_ctl) {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003885 int val;
3886 snd_hda_codec_write_cache(codec, nid, 0,
3887 AC_VERB_SET_PIN_WIDGET_CONTROL,
3888 new_ctl);
Takashi Iwai47fd8302007-08-10 17:11:07 +02003889 val = ucontrol->value.enumerated.item[0] >= 3 ?
3890 HDA_AMP_MUTE : 0;
3891 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3892 HDA_AMP_MUTE, val);
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003893 return 1;
3894 }
3895 return 0;
3896}
3897
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003898static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
3899 struct snd_ctl_elem_info *uinfo)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003900{
3901 static char *texts[] = {
3902 "Front", "Surround", "CLFE", "Side"
3903 };
3904 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3905 uinfo->count = 1;
3906 uinfo->value.enumerated.items = 4;
3907 if (uinfo->value.enumerated.item >= 4)
3908 uinfo->value.enumerated.item = 3;
3909 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3910 return 0;
3911}
3912
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003913static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
3914 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003915{
3916 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3917 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
3918 unsigned int sel;
3919
3920 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
3921 ucontrol->value.enumerated.item[0] = sel & 3;
3922 return 0;
3923}
3924
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003925static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
3926 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003927{
3928 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3929 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
3930 unsigned int sel;
3931
3932 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
3933 if (ucontrol->value.enumerated.item[0] != sel) {
3934 sel = ucontrol->value.enumerated.item[0] & 3;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003935 snd_hda_codec_write_cache(codec, nid, 0,
3936 AC_VERB_SET_CONNECT_SEL, sel);
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003937 return 1;
3938 }
3939 return 0;
3940}
3941
3942#define PIN_CTL_TEST(xname,nid) { \
3943 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3944 .name = xname, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01003945 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003946 .info = alc_test_pin_ctl_info, \
3947 .get = alc_test_pin_ctl_get, \
3948 .put = alc_test_pin_ctl_put, \
3949 .private_value = nid \
3950 }
3951
3952#define PIN_SRC_TEST(xname,nid) { \
3953 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3954 .name = xname, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01003955 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003956 .info = alc_test_pin_src_info, \
3957 .get = alc_test_pin_src_get, \
3958 .put = alc_test_pin_src_put, \
3959 .private_value = nid \
3960 }
3961
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01003962static struct snd_kcontrol_new alc880_test_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02003963 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3964 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3965 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
3966 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01003967 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3968 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
3969 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
3970 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003971 PIN_CTL_TEST("Front Pin Mode", 0x14),
3972 PIN_CTL_TEST("Surround Pin Mode", 0x15),
3973 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
3974 PIN_CTL_TEST("Side Pin Mode", 0x17),
3975 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
3976 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
3977 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
3978 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
3979 PIN_SRC_TEST("In-1 Pin Source", 0x18),
3980 PIN_SRC_TEST("In-2 Pin Source", 0x19),
3981 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
3982 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
3983 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
3984 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
3985 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
3986 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
3987 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
3988 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
3989 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
3990 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
3991 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
3992 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003993 {
3994 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3995 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01003996 .info = alc_ch_mode_info,
3997 .get = alc_ch_mode_get,
3998 .put = alc_ch_mode_put,
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003999 },
4000 { } /* end */
4001};
4002
4003static struct hda_verb alc880_test_init_verbs[] = {
4004 /* Unmute inputs of 0x0c - 0x0f */
Takashi Iwai05acb862005-06-10 19:50:25 +02004005 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4006 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4007 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4008 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4009 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4010 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4011 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4012 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004013 /* Vol output for 0x0c-0x0f */
Takashi Iwai05acb862005-06-10 19:50:25 +02004014 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4015 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4016 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4017 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004018 /* Set output pins 0x14-0x17 */
Takashi Iwai05acb862005-06-10 19:50:25 +02004019 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4020 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4021 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4022 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004023 /* Unmute output pins 0x14-0x17 */
Takashi Iwai05acb862005-06-10 19:50:25 +02004024 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4025 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4026 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4027 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004028 /* Set input pins 0x18-0x1c */
Takashi Iwai16ded522005-06-10 19:58:24 +02004029 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4030 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwai05acb862005-06-10 19:50:25 +02004031 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4032 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4033 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004034 /* Mute input pins 0x18-0x1b */
Takashi Iwai05acb862005-06-10 19:50:25 +02004035 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4036 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4037 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4038 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004039 /* ADC set up */
Takashi Iwai05acb862005-06-10 19:50:25 +02004040 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004041 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004042 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004043 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004044 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004045 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004046 /* Analog input/passthru */
4047 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4048 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4049 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4050 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4051 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004052 { }
4053};
4054#endif
4055
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056/*
4057 */
4058
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004059static const char *alc880_models[ALC880_MODEL_LAST] = {
4060 [ALC880_3ST] = "3stack",
4061 [ALC880_TCL_S700] = "tcl",
4062 [ALC880_3ST_DIG] = "3stack-digout",
4063 [ALC880_CLEVO] = "clevo",
4064 [ALC880_5ST] = "5stack",
4065 [ALC880_5ST_DIG] = "5stack-digout",
4066 [ALC880_W810] = "w810",
4067 [ALC880_Z71V] = "z71v",
4068 [ALC880_6ST] = "6stack",
4069 [ALC880_6ST_DIG] = "6stack-digout",
4070 [ALC880_ASUS] = "asus",
4071 [ALC880_ASUS_W1V] = "asus-w1v",
4072 [ALC880_ASUS_DIG] = "asus-dig",
4073 [ALC880_ASUS_DIG2] = "asus-dig2",
4074 [ALC880_UNIWILL_DIG] = "uniwill",
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004075 [ALC880_UNIWILL_P53] = "uniwill-p53",
4076 [ALC880_FUJITSU] = "fujitsu",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004077 [ALC880_F1734] = "F1734",
4078 [ALC880_LG] = "lg",
4079 [ALC880_LG_LW] = "lg-lw",
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004080 [ALC880_MEDION_RIM] = "medion",
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004081#ifdef CONFIG_SND_DEBUG
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004082 [ALC880_TEST] = "test",
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004083#endif
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004084 [ALC880_AUTO] = "auto",
4085};
4086
4087static struct snd_pci_quirk alc880_cfg_tbl[] = {
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004088 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004089 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
4090 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
4091 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
4092 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
4093 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
4094 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
4095 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
4096 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004097 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
4098 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004099 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
4100 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
4101 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
4102 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
4103 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
4104 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
4105 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
4106 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
4107 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
4108 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
Travis Place186c3112008-05-20 11:54:41 +02004109 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004110 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
4111 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
4112 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
Takashi Iwaidea0a502009-02-09 17:14:52 +01004113 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004114 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004115 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
4116 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004117 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
4118 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004119 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
4120 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
4121 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
4122 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004123 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
4124 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004125 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004126 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004127 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004128 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004129 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
4130 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004131 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004132 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004133 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004134 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004135 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
Travis Place1d116042008-06-23 11:42:30 +02004136 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004137 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004138 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004139 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004140 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
4141 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004142 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004143 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
4144 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
4145 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
4146 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004147 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
4148 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004149 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004150 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004151 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
4152 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004153 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
4154 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
4155 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +01004156 /* default Intel */
4157 SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004158 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
4159 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 {}
4161};
4162
Takashi Iwai16ded522005-06-10 19:58:24 +02004163/*
Kailang Yangdf694da2005-12-05 19:42:22 +01004164 * ALC880 codec presets
Takashi Iwai16ded522005-06-10 19:58:24 +02004165 */
Takashi Iwai16ded522005-06-10 19:58:24 +02004166static struct alc_config_preset alc880_presets[] = {
4167 [ALC880_3ST] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004168 .mixers = { alc880_three_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004169 .init_verbs = { alc880_volume_init_verbs,
4170 alc880_pin_3stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004171 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwai16ded522005-06-10 19:58:24 +02004172 .dac_nids = alc880_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004173 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4174 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004175 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004176 .input_mux = &alc880_capture_source,
4177 },
4178 [ALC880_3ST_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004179 .mixers = { alc880_three_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004180 .init_verbs = { alc880_volume_init_verbs,
4181 alc880_pin_3stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004182 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwai16ded522005-06-10 19:58:24 +02004183 .dac_nids = alc880_dac_nids,
4184 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004185 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4186 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004187 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004188 .input_mux = &alc880_capture_source,
4189 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004190 [ALC880_TCL_S700] = {
4191 .mixers = { alc880_tcl_s700_mixer },
4192 .init_verbs = { alc880_volume_init_verbs,
4193 alc880_pin_tcl_S700_init_verbs,
4194 alc880_gpio2_init_verbs },
4195 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4196 .dac_nids = alc880_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01004197 .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
4198 .num_adc_nids = 1, /* single ADC */
Kailang Yangdf694da2005-12-05 19:42:22 +01004199 .hp_nid = 0x03,
4200 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4201 .channel_mode = alc880_2_jack_modes,
4202 .input_mux = &alc880_capture_source,
4203 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004204 [ALC880_5ST] = {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004205 .mixers = { alc880_three_stack_mixer,
4206 alc880_five_stack_mixer},
4207 .init_verbs = { alc880_volume_init_verbs,
4208 alc880_pin_5stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004209 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4210 .dac_nids = alc880_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004211 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
4212 .channel_mode = alc880_fivestack_modes,
4213 .input_mux = &alc880_capture_source,
4214 },
4215 [ALC880_5ST_DIG] = {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004216 .mixers = { alc880_three_stack_mixer,
4217 alc880_five_stack_mixer },
4218 .init_verbs = { alc880_volume_init_verbs,
4219 alc880_pin_5stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004220 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4221 .dac_nids = alc880_dac_nids,
4222 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004223 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
4224 .channel_mode = alc880_fivestack_modes,
4225 .input_mux = &alc880_capture_source,
4226 },
Takashi Iwaib6482d42005-06-27 15:32:43 +02004227 [ALC880_6ST] = {
4228 .mixers = { alc880_six_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004229 .init_verbs = { alc880_volume_init_verbs,
4230 alc880_pin_6stack_init_verbs },
Takashi Iwaib6482d42005-06-27 15:32:43 +02004231 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
4232 .dac_nids = alc880_6st_dac_nids,
4233 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
4234 .channel_mode = alc880_sixstack_modes,
4235 .input_mux = &alc880_6stack_capture_source,
4236 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004237 [ALC880_6ST_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004238 .mixers = { alc880_six_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004239 .init_verbs = { alc880_volume_init_verbs,
4240 alc880_pin_6stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004241 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
4242 .dac_nids = alc880_6st_dac_nids,
4243 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004244 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
4245 .channel_mode = alc880_sixstack_modes,
4246 .input_mux = &alc880_6stack_capture_source,
4247 },
4248 [ALC880_W810] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004249 .mixers = { alc880_w810_base_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004250 .init_verbs = { alc880_volume_init_verbs,
4251 alc880_pin_w810_init_verbs,
Takashi Iwaib0af0de2005-06-21 14:49:19 +02004252 alc880_gpio2_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004253 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
4254 .dac_nids = alc880_w810_dac_nids,
4255 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004256 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
4257 .channel_mode = alc880_w810_modes,
4258 .input_mux = &alc880_capture_source,
4259 },
4260 [ALC880_Z71V] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004261 .mixers = { alc880_z71v_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004262 .init_verbs = { alc880_volume_init_verbs,
4263 alc880_pin_z71v_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004264 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
4265 .dac_nids = alc880_z71v_dac_nids,
4266 .dig_out_nid = ALC880_DIGOUT_NID,
4267 .hp_nid = 0x03,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004268 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4269 .channel_mode = alc880_2_jack_modes,
Takashi Iwai16ded522005-06-10 19:58:24 +02004270 .input_mux = &alc880_capture_source,
4271 },
4272 [ALC880_F1734] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004273 .mixers = { alc880_f1734_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004274 .init_verbs = { alc880_volume_init_verbs,
4275 alc880_pin_f1734_init_verbs },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004276 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
4277 .dac_nids = alc880_f1734_dac_nids,
4278 .hp_nid = 0x02,
4279 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4280 .channel_mode = alc880_2_jack_modes,
Takashi Iwai937b4162008-02-11 14:52:36 +01004281 .input_mux = &alc880_f1734_capture_source,
4282 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004283 .setup = alc880_uniwill_p53_setup,
4284 .init_hook = alc_automute_amp,
Takashi Iwai16ded522005-06-10 19:58:24 +02004285 },
4286 [ALC880_ASUS] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004287 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004288 .init_verbs = { alc880_volume_init_verbs,
4289 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004290 alc880_gpio1_init_verbs },
4291 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4292 .dac_nids = alc880_asus_dac_nids,
4293 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4294 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004295 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004296 .input_mux = &alc880_capture_source,
4297 },
4298 [ALC880_ASUS_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004299 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004300 .init_verbs = { alc880_volume_init_verbs,
4301 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004302 alc880_gpio1_init_verbs },
4303 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4304 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004305 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004306 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4307 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004308 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004309 .input_mux = &alc880_capture_source,
4310 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004311 [ALC880_ASUS_DIG2] = {
4312 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004313 .init_verbs = { alc880_volume_init_verbs,
4314 alc880_pin_asus_init_verbs,
Kailang Yangdf694da2005-12-05 19:42:22 +01004315 alc880_gpio2_init_verbs }, /* use GPIO2 */
4316 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4317 .dac_nids = alc880_asus_dac_nids,
4318 .dig_out_nid = ALC880_DIGOUT_NID,
4319 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4320 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004321 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +01004322 .input_mux = &alc880_capture_source,
4323 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004324 [ALC880_ASUS_W1V] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004325 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004326 .init_verbs = { alc880_volume_init_verbs,
4327 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004328 alc880_gpio1_init_verbs },
4329 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4330 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004331 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004332 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4333 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004334 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004335 .input_mux = &alc880_capture_source,
4336 },
4337 [ALC880_UNIWILL_DIG] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01004338 .mixers = { alc880_asus_mixer },
Kailang Yangccc656c2006-10-17 12:32:26 +02004339 .init_verbs = { alc880_volume_init_verbs,
4340 alc880_pin_asus_init_verbs },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004341 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4342 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004343 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004344 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4345 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004346 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004347 .input_mux = &alc880_capture_source,
4348 },
Kailang Yangccc656c2006-10-17 12:32:26 +02004349 [ALC880_UNIWILL] = {
4350 .mixers = { alc880_uniwill_mixer },
4351 .init_verbs = { alc880_volume_init_verbs,
4352 alc880_uniwill_init_verbs },
4353 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4354 .dac_nids = alc880_asus_dac_nids,
4355 .dig_out_nid = ALC880_DIGOUT_NID,
4356 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4357 .channel_mode = alc880_threestack_modes,
4358 .need_dac_fix = 1,
4359 .input_mux = &alc880_capture_source,
4360 .unsol_event = alc880_uniwill_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004361 .setup = alc880_uniwill_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004362 .init_hook = alc880_uniwill_init_hook,
Kailang Yangccc656c2006-10-17 12:32:26 +02004363 },
4364 [ALC880_UNIWILL_P53] = {
4365 .mixers = { alc880_uniwill_p53_mixer },
4366 .init_verbs = { alc880_volume_init_verbs,
4367 alc880_uniwill_p53_init_verbs },
4368 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4369 .dac_nids = alc880_asus_dac_nids,
4370 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004371 .channel_mode = alc880_threestack_modes,
4372 .input_mux = &alc880_capture_source,
4373 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004374 .setup = alc880_uniwill_p53_setup,
4375 .init_hook = alc_automute_amp,
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004376 },
4377 [ALC880_FUJITSU] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01004378 .mixers = { alc880_fujitsu_mixer },
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004379 .init_verbs = { alc880_volume_init_verbs,
4380 alc880_uniwill_p53_init_verbs,
4381 alc880_beep_init_verbs },
4382 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4383 .dac_nids = alc880_dac_nids,
Takashi Iwaid53d7d92007-08-20 15:20:02 +02004384 .dig_out_nid = ALC880_DIGOUT_NID,
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004385 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4386 .channel_mode = alc880_2_jack_modes,
Kailang Yangccc656c2006-10-17 12:32:26 +02004387 .input_mux = &alc880_capture_source,
4388 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004389 .setup = alc880_uniwill_p53_setup,
4390 .init_hook = alc_automute_amp,
Kailang Yangccc656c2006-10-17 12:32:26 +02004391 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004392 [ALC880_CLEVO] = {
4393 .mixers = { alc880_three_stack_mixer },
4394 .init_verbs = { alc880_volume_init_verbs,
4395 alc880_pin_clevo_init_verbs },
4396 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4397 .dac_nids = alc880_dac_nids,
4398 .hp_nid = 0x03,
4399 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4400 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004401 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +01004402 .input_mux = &alc880_capture_source,
4403 },
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004404 [ALC880_LG] = {
4405 .mixers = { alc880_lg_mixer },
4406 .init_verbs = { alc880_volume_init_verbs,
4407 alc880_lg_init_verbs },
4408 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
4409 .dac_nids = alc880_lg_dac_nids,
4410 .dig_out_nid = ALC880_DIGOUT_NID,
4411 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
4412 .channel_mode = alc880_lg_ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004413 .need_dac_fix = 1,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004414 .input_mux = &alc880_lg_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004415 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004416 .setup = alc880_lg_setup,
4417 .init_hook = alc_automute_amp,
Takashi Iwaicb53c622007-08-10 17:21:45 +02004418#ifdef CONFIG_SND_HDA_POWER_SAVE
4419 .loopbacks = alc880_lg_loopbacks,
4420#endif
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004421 },
Takashi Iwaid6815182006-03-23 16:06:23 +01004422 [ALC880_LG_LW] = {
4423 .mixers = { alc880_lg_lw_mixer },
4424 .init_verbs = { alc880_volume_init_verbs,
4425 alc880_lg_lw_init_verbs },
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02004426 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwaid6815182006-03-23 16:06:23 +01004427 .dac_nids = alc880_dac_nids,
4428 .dig_out_nid = ALC880_DIGOUT_NID,
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02004429 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
4430 .channel_mode = alc880_lg_lw_modes,
Takashi Iwaid6815182006-03-23 16:06:23 +01004431 .input_mux = &alc880_lg_lw_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004432 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004433 .setup = alc880_lg_lw_setup,
4434 .init_hook = alc_automute_amp,
Takashi Iwaid6815182006-03-23 16:06:23 +01004435 },
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004436 [ALC880_MEDION_RIM] = {
4437 .mixers = { alc880_medion_rim_mixer },
4438 .init_verbs = { alc880_volume_init_verbs,
4439 alc880_medion_rim_init_verbs,
4440 alc_gpio2_init_verbs },
4441 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4442 .dac_nids = alc880_dac_nids,
4443 .dig_out_nid = ALC880_DIGOUT_NID,
4444 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4445 .channel_mode = alc880_2_jack_modes,
4446 .input_mux = &alc880_medion_rim_capture_source,
4447 .unsol_event = alc880_medion_rim_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004448 .setup = alc880_medion_rim_setup,
4449 .init_hook = alc880_medion_rim_automute,
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004450 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004451#ifdef CONFIG_SND_DEBUG
4452 [ALC880_TEST] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004453 .mixers = { alc880_test_mixer },
4454 .init_verbs = { alc880_test_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004455 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
4456 .dac_nids = alc880_test_dac_nids,
4457 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004458 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
4459 .channel_mode = alc880_test_modes,
4460 .input_mux = &alc880_test_capture_source,
4461 },
4462#endif
4463};
4464
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004465/*
4466 * Automatic parse of I/O pins from the BIOS configuration
4467 */
4468
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004469enum {
4470 ALC_CTL_WIDGET_VOL,
4471 ALC_CTL_WIDGET_MUTE,
4472 ALC_CTL_BIND_MUTE,
4473};
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01004474static struct snd_kcontrol_new alc880_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004475 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
4476 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01004477 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004478};
4479
4480/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004481static int add_control(struct alc_spec *spec, int type, const char *name,
4482 unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004483{
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01004484 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004485
Takashi Iwai603c4012008-07-30 15:01:44 +02004486 snd_array_init(&spec->kctls, sizeof(*knew), 32);
4487 knew = snd_array_new(&spec->kctls);
4488 if (!knew)
4489 return -ENOMEM;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004490 *knew = alc880_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07004491 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004492 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004493 return -ENOMEM;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01004494 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01004495 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004496 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004497 return 0;
4498}
4499
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004500static int add_control_with_pfx(struct alc_spec *spec, int type,
4501 const char *pfx, const char *dir,
4502 const char *sfx, unsigned long val)
4503{
4504 char name[32];
4505 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
4506 return add_control(spec, type, name, val);
4507}
4508
4509#define add_pb_vol_ctrl(spec, type, pfx, val) \
4510 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val)
4511#define add_pb_sw_ctrl(spec, type, pfx, val) \
4512 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val)
4513
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004514#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
4515#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
4516#define alc880_is_multi_pin(nid) ((nid) >= 0x18)
4517#define alc880_multi_pin_idx(nid) ((nid) - 0x18)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004518#define alc880_idx_to_dac(nid) ((nid) + 0x02)
4519#define alc880_dac_to_idx(nid) ((nid) - 0x02)
4520#define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
4521#define alc880_idx_to_selector(nid) ((nid) + 0x10)
4522#define ALC880_PIN_CD_NID 0x1c
4523
4524/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004525static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
4526 const struct auto_pin_cfg *cfg)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004527{
4528 hda_nid_t nid;
4529 int assigned[4];
4530 int i, j;
4531
4532 memset(assigned, 0, sizeof(assigned));
Takashi Iwaib0af0de2005-06-21 14:49:19 +02004533 spec->multiout.dac_nids = spec->private_dac_nids;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004534
4535 /* check the pins hardwired to audio widget */
4536 for (i = 0; i < cfg->line_outs; i++) {
4537 nid = cfg->line_out_pins[i];
4538 if (alc880_is_fixed_pin(nid)) {
4539 int idx = alc880_fixed_pin_idx(nid);
Libin Yang5014f192005-11-23 15:48:36 +01004540 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004541 assigned[idx] = 1;
4542 }
4543 }
4544 /* left pins can be connect to any audio widget */
4545 for (i = 0; i < cfg->line_outs; i++) {
4546 nid = cfg->line_out_pins[i];
4547 if (alc880_is_fixed_pin(nid))
4548 continue;
4549 /* search for an empty channel */
4550 for (j = 0; j < cfg->line_outs; j++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004551 if (!assigned[j]) {
4552 spec->multiout.dac_nids[i] =
4553 alc880_idx_to_dac(j);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004554 assigned[j] = 1;
4555 break;
4556 }
4557 }
4558 }
4559 spec->multiout.num_dacs = cfg->line_outs;
4560 return 0;
4561}
4562
4563/* add playback controls from the parsed DAC table */
Kailang Yangdf694da2005-12-05 19:42:22 +01004564static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
4565 const struct auto_pin_cfg *cfg)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004566{
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004567 static const char *chname[4] = {
4568 "Front", "Surround", NULL /*CLFE*/, "Side"
4569 };
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004570 hda_nid_t nid;
4571 int i, err;
4572
4573 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004574 if (!spec->multiout.dac_nids[i])
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004575 continue;
4576 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
4577 if (i == 2) {
4578 /* Center/LFE */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004579 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
4580 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004581 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
4582 HDA_OUTPUT));
4583 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004584 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004585 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
4586 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004587 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
4588 HDA_OUTPUT));
4589 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004590 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004591 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
4592 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004593 HDA_COMPOSE_AMP_VAL(nid, 1, 2,
4594 HDA_INPUT));
4595 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004596 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004597 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
4598 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004599 HDA_COMPOSE_AMP_VAL(nid, 2, 2,
4600 HDA_INPUT));
4601 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004602 return err;
4603 } else {
Takashi Iwaicb162b62009-08-25 16:05:03 +02004604 const char *pfx;
4605 if (cfg->line_outs == 1 &&
4606 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
4607 pfx = "Speaker";
4608 else
4609 pfx = chname[i];
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004610 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004611 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
4612 HDA_OUTPUT));
4613 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004614 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004615 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004616 HDA_COMPOSE_AMP_VAL(nid, 3, 2,
4617 HDA_INPUT));
4618 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004619 return err;
4620 }
4621 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004622 return 0;
4623}
4624
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004625/* add playback controls for speaker and HP outputs */
4626static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
4627 const char *pfx)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004628{
4629 hda_nid_t nid;
4630 int err;
4631
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004632 if (!pin)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004633 return 0;
4634
4635 if (alc880_is_fixed_pin(pin)) {
4636 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
Takashi Iwai82bc9552006-03-21 11:24:42 +01004637 /* specify the DAC as the extra output */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004638 if (!spec->multiout.hp_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004639 spec->multiout.hp_nid = nid;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004640 else
4641 spec->multiout.extra_out_nid[0] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004642 /* control HP volume/switch on the output mixer amp */
4643 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004644 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004645 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
4646 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004647 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004648 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004649 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
4650 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004651 return err;
4652 } else if (alc880_is_multi_pin(pin)) {
4653 /* set manual connection */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004654 /* we have only a switch on HP-out PIN */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004655 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004656 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
4657 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004658 return err;
4659 }
4660 return 0;
4661}
4662
4663/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004664static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
4665 const char *ctlname,
Kailang Yangdf694da2005-12-05 19:42:22 +01004666 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004667{
Kailang Yangdf694da2005-12-05 19:42:22 +01004668 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004669
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004670 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004671 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4672 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004673 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004674 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004675 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4676 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004677 return err;
4678 return 0;
4679}
4680
Takashi Iwai05f5f472009-08-25 13:10:18 +02004681static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004682{
Takashi Iwai05f5f472009-08-25 13:10:18 +02004683 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
4684 return (pincap & AC_PINCAP_IN) != 0;
4685}
4686
4687/* create playback/capture controls for input pins */
4688static int alc_auto_create_input_ctls(struct hda_codec *codec,
4689 const struct auto_pin_cfg *cfg,
4690 hda_nid_t mixer,
4691 hda_nid_t cap1, hda_nid_t cap2)
4692{
4693 struct alc_spec *spec = codec->spec;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02004694 struct hda_input_mux *imux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01004695 int i, err, idx;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004696
4697 for (i = 0; i < AUTO_PIN_LAST; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02004698 hda_nid_t pin;
4699
4700 pin = cfg->input_pins[i];
4701 if (!alc_is_input_pin(codec, pin))
4702 continue;
4703
4704 if (mixer) {
4705 idx = get_connection_index(codec, mixer, pin);
4706 if (idx >= 0) {
4707 err = new_analog_input(spec, pin,
4708 auto_pin_cfg_labels[i],
4709 idx, mixer);
4710 if (err < 0)
4711 return err;
4712 }
4713 }
4714
4715 if (!cap1)
4716 continue;
4717 idx = get_connection_index(codec, cap1, pin);
4718 if (idx < 0 && cap2)
4719 idx = get_connection_index(codec, cap2, pin);
4720 if (idx >= 0) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004721 imux->items[imux->num_items].label =
4722 auto_pin_cfg_labels[i];
Takashi Iwai05f5f472009-08-25 13:10:18 +02004723 imux->items[imux->num_items].index = idx;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004724 imux->num_items++;
4725 }
4726 }
4727 return 0;
4728}
4729
Takashi Iwai05f5f472009-08-25 13:10:18 +02004730static int alc880_auto_create_input_ctls(struct hda_codec *codec,
4731 const struct auto_pin_cfg *cfg)
4732{
4733 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x08, 0x09);
4734}
4735
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004736static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
4737 unsigned int pin_type)
4738{
4739 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4740 pin_type);
4741 /* unmute pin */
Takashi Iwaid260cdf2008-02-13 17:19:35 +01004742 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4743 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004744}
4745
Kailang Yangdf694da2005-12-05 19:42:22 +01004746static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
4747 hda_nid_t nid, int pin_type,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004748 int dac_idx)
4749{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004750 alc_set_pin_output(codec, nid, pin_type);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004751 /* need the manual connection? */
4752 if (alc880_is_multi_pin(nid)) {
4753 struct alc_spec *spec = codec->spec;
4754 int idx = alc880_multi_pin_idx(nid);
4755 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
4756 AC_VERB_SET_CONNECT_SEL,
4757 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
4758 }
4759}
4760
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02004761static int get_pin_type(int line_out_type)
4762{
4763 if (line_out_type == AUTO_PIN_HP_OUT)
4764 return PIN_HP;
4765 else
4766 return PIN_OUT;
4767}
4768
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004769static void alc880_auto_init_multi_out(struct hda_codec *codec)
4770{
4771 struct alc_spec *spec = codec->spec;
4772 int i;
Kailang Yangea1fb292008-08-26 12:58:38 +02004773
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004774 for (i = 0; i < spec->autocfg.line_outs; i++) {
4775 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02004776 int pin_type = get_pin_type(spec->autocfg.line_out_type);
4777 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004778 }
4779}
4780
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004781static void alc880_auto_init_extra_out(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004782{
4783 struct alc_spec *spec = codec->spec;
4784 hda_nid_t pin;
4785
Takashi Iwai82bc9552006-03-21 11:24:42 +01004786 pin = spec->autocfg.speaker_pins[0];
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004787 if (pin) /* connect to front */
4788 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004789 pin = spec->autocfg.hp_pins[0];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004790 if (pin) /* connect to front */
4791 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
4792}
4793
4794static void alc880_auto_init_analog_input(struct hda_codec *codec)
4795{
4796 struct alc_spec *spec = codec->spec;
4797 int i;
4798
4799 for (i = 0; i < AUTO_PIN_LAST; i++) {
4800 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai05f5f472009-08-25 13:10:18 +02004801 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +01004802 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +01004803 if (nid != ALC880_PIN_CD_NID &&
4804 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004805 snd_hda_codec_write(codec, nid, 0,
4806 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004807 AMP_OUT_MUTE);
4808 }
4809 }
4810}
4811
Takashi Iwai7f311a42010-04-09 17:32:23 +02004812static void alc880_auto_init_input_src(struct hda_codec *codec)
4813{
4814 struct alc_spec *spec = codec->spec;
4815 int c;
4816
4817 for (c = 0; c < spec->num_adc_nids; c++) {
4818 unsigned int mux_idx;
4819 const struct hda_input_mux *imux;
4820 mux_idx = c >= spec->num_mux_defs ? 0 : c;
4821 imux = &spec->input_mux[mux_idx];
4822 if (!imux->num_items && mux_idx > 0)
4823 imux = &spec->input_mux[0];
4824 if (imux)
4825 snd_hda_codec_write(codec, spec->adc_nids[c], 0,
4826 AC_VERB_SET_CONNECT_SEL,
4827 imux->items[0].index);
4828 }
4829}
4830
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004831/* parse the BIOS configuration and set up the alc_spec */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004832/* return 1 if successful, 0 if the proper config is not found,
4833 * or a negative error code
4834 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004835static int alc880_parse_auto_config(struct hda_codec *codec)
4836{
4837 struct alc_spec *spec = codec->spec;
Takashi Iwai6a05ac42009-02-13 11:19:09 +01004838 int i, err;
Kailang Yangdf694da2005-12-05 19:42:22 +01004839 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004840
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004841 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4842 alc880_ignore);
4843 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004844 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004845 if (!spec->autocfg.line_outs)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004846 return 0; /* can't find valid BIOS pin config */
Kailang Yangdf694da2005-12-05 19:42:22 +01004847
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004848 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
4849 if (err < 0)
4850 return err;
4851 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
4852 if (err < 0)
4853 return err;
4854 err = alc880_auto_create_extra_out(spec,
4855 spec->autocfg.speaker_pins[0],
4856 "Speaker");
4857 if (err < 0)
4858 return err;
4859 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
4860 "Headphone");
4861 if (err < 0)
4862 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +02004863 err = alc880_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004864 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004865 return err;
4866
4867 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4868
Takashi Iwai6a05ac42009-02-13 11:19:09 +01004869 /* check multiple SPDIF-out (for recent codecs) */
4870 for (i = 0; i < spec->autocfg.dig_outs; i++) {
4871 hda_nid_t dig_nid;
4872 err = snd_hda_get_connections(codec,
4873 spec->autocfg.dig_out_pins[i],
4874 &dig_nid, 1);
4875 if (err < 0)
4876 continue;
4877 if (!i)
4878 spec->multiout.dig_out_nid = dig_nid;
4879 else {
4880 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
Roel Kluin71121d9f2009-11-10 20:11:55 +01004881 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
Takashi Iwai6a05ac42009-02-13 11:19:09 +01004882 break;
Roel Kluin71121d9f2009-11-10 20:11:55 +01004883 spec->slave_dig_outs[i - 1] = dig_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +01004884 }
4885 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004886 if (spec->autocfg.dig_in_pin)
4887 spec->dig_in_nid = ALC880_DIGIN_NID;
4888
Takashi Iwai603c4012008-07-30 15:01:44 +02004889 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +01004890 add_mixer(spec, spec->kctls.list);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004891
Takashi Iwaid88897e2008-10-31 15:01:37 +01004892 add_verb(spec, alc880_volume_init_verbs);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004893
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02004894 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02004895 spec->input_mux = &spec->private_imux[0];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004896
Kailang Yang6227cdc2010-02-25 08:36:52 +01004897 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02004898
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004899 return 1;
4900}
4901
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004902/* additional initialization for auto-configuration model */
4903static void alc880_auto_init(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004904{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004905 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004906 alc880_auto_init_multi_out(codec);
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004907 alc880_auto_init_extra_out(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004908 alc880_auto_init_analog_input(codec);
Takashi Iwai7f311a42010-04-09 17:32:23 +02004909 alc880_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004910 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +02004911 alc_inithook(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004912}
4913
Takashi Iwaib59bdf32009-08-11 09:47:30 +02004914/* check the ADC/MUX contains all input pins; some ADC/MUX contains only
4915 * one of two digital mic pins, e.g. on ALC272
4916 */
4917static void fixup_automic_adc(struct hda_codec *codec)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01004918{
Takashi Iwaib59bdf32009-08-11 09:47:30 +02004919 struct alc_spec *spec = codec->spec;
4920 int i;
4921
4922 for (i = 0; i < spec->num_adc_nids; i++) {
4923 hda_nid_t cap = spec->capsrc_nids ?
4924 spec->capsrc_nids[i] : spec->adc_nids[i];
4925 int iidx, eidx;
4926
4927 iidx = get_connection_index(codec, cap, spec->int_mic.pin);
4928 if (iidx < 0)
4929 continue;
4930 eidx = get_connection_index(codec, cap, spec->ext_mic.pin);
4931 if (eidx < 0)
4932 continue;
4933 spec->int_mic.mux_idx = iidx;
4934 spec->ext_mic.mux_idx = eidx;
4935 if (spec->capsrc_nids)
4936 spec->capsrc_nids += i;
4937 spec->adc_nids += i;
4938 spec->num_adc_nids = 1;
4939 return;
4940 }
4941 snd_printd(KERN_INFO "hda_codec: %s: "
4942 "No ADC/MUX containing both 0x%x and 0x%x pins\n",
4943 codec->chip_name, spec->int_mic.pin, spec->ext_mic.pin);
4944 spec->auto_mic = 0; /* disable auto-mic to be sure */
4945}
4946
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01004947/* choose the ADC/MUX containing the input pin and initialize the setup */
4948static void fixup_single_adc(struct hda_codec *codec)
4949{
4950 struct alc_spec *spec = codec->spec;
Frederik Deweerdtd2db09b2010-03-05 16:34:31 +01004951 hda_nid_t pin = 0;
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01004952 int i;
4953
4954 /* search for the input pin; there must be only one */
4955 for (i = 0; i < AUTO_PIN_LAST; i++) {
4956 if (spec->autocfg.input_pins[i]) {
4957 pin = spec->autocfg.input_pins[i];
4958 break;
4959 }
4960 }
4961 if (!pin)
4962 return;
4963
4964 /* set the default connection to that pin */
4965 for (i = 0; i < spec->num_adc_nids; i++) {
4966 hda_nid_t cap = spec->capsrc_nids ?
4967 spec->capsrc_nids[i] : spec->adc_nids[i];
4968 int idx;
4969
4970 idx = get_connection_index(codec, cap, pin);
4971 if (idx < 0)
4972 continue;
4973 /* use only this ADC */
4974 if (spec->capsrc_nids)
4975 spec->capsrc_nids += i;
4976 spec->adc_nids += i;
4977 spec->num_adc_nids = 1;
4978 /* select or unmute this route */
4979 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
4980 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
4981 HDA_AMP_MUTE, 0);
4982 } else {
4983 snd_hda_codec_write_cache(codec, cap, 0,
4984 AC_VERB_SET_CONNECT_SEL, idx);
4985 }
4986 return;
4987 }
4988}
4989
Takashi Iwaib59bdf32009-08-11 09:47:30 +02004990static void set_capture_mixer(struct hda_codec *codec)
4991{
4992 struct alc_spec *spec = codec->spec;
Takashi Iwaia23b6882009-03-23 15:21:36 +01004993 static struct snd_kcontrol_new *caps[2][3] = {
4994 { alc_capture_mixer_nosrc1,
4995 alc_capture_mixer_nosrc2,
4996 alc_capture_mixer_nosrc3 },
4997 { alc_capture_mixer1,
4998 alc_capture_mixer2,
4999 alc_capture_mixer3 },
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005000 };
Takashi Iwaia23b6882009-03-23 15:21:36 +01005001 if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005002 int mux = 0;
5003 if (spec->auto_mic)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005004 fixup_automic_adc(codec);
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005005 else if (spec->input_mux) {
5006 if (spec->input_mux->num_items > 1)
5007 mux = 1;
5008 else if (spec->input_mux->num_items == 1)
5009 fixup_single_adc(codec);
5010 }
Takashi Iwaia23b6882009-03-23 15:21:36 +01005011 spec->cap_mixer = caps[mux][spec->num_adc_nids - 1];
5012 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005013}
5014
Takashi Iwai66946352010-03-29 17:21:45 +02005015/* fill adc_nids (and capsrc_nids) containing all active input pins */
5016static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
5017 int num_nids)
5018{
5019 struct alc_spec *spec = codec->spec;
5020 int n;
5021 hda_nid_t fallback_adc = 0, fallback_cap = 0;
5022
5023 for (n = 0; n < num_nids; n++) {
5024 hda_nid_t adc, cap;
5025 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
5026 int nconns, i, j;
5027
5028 adc = nids[n];
5029 if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN)
5030 continue;
5031 cap = adc;
5032 nconns = snd_hda_get_connections(codec, cap, conn,
5033 ARRAY_SIZE(conn));
5034 if (nconns == 1) {
5035 cap = conn[0];
5036 nconns = snd_hda_get_connections(codec, cap, conn,
5037 ARRAY_SIZE(conn));
5038 }
5039 if (nconns <= 0)
5040 continue;
5041 if (!fallback_adc) {
5042 fallback_adc = adc;
5043 fallback_cap = cap;
5044 }
5045 for (i = 0; i < AUTO_PIN_LAST; i++) {
5046 hda_nid_t nid = spec->autocfg.input_pins[i];
5047 if (!nid)
5048 continue;
5049 for (j = 0; j < nconns; j++) {
5050 if (conn[j] == nid)
5051 break;
5052 }
5053 if (j >= nconns)
5054 break;
5055 }
5056 if (i >= AUTO_PIN_LAST) {
5057 int num_adcs = spec->num_adc_nids;
5058 spec->private_adc_nids[num_adcs] = adc;
5059 spec->private_capsrc_nids[num_adcs] = cap;
5060 spec->num_adc_nids++;
5061 spec->adc_nids = spec->private_adc_nids;
5062 if (adc != cap)
5063 spec->capsrc_nids = spec->private_capsrc_nids;
5064 }
5065 }
5066 if (!spec->num_adc_nids) {
5067 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
Takashi Iwai1f85d722010-03-30 07:48:05 +02005068 " using fallback 0x%x\n",
5069 codec->chip_name, fallback_adc);
Takashi Iwai66946352010-03-29 17:21:45 +02005070 spec->private_adc_nids[0] = fallback_adc;
5071 spec->adc_nids = spec->private_adc_nids;
5072 if (fallback_adc != fallback_cap) {
5073 spec->private_capsrc_nids[0] = fallback_cap;
5074 spec->capsrc_nids = spec->private_adc_nids;
5075 }
5076 }
5077}
5078
Takashi Iwai67d634c2009-11-16 15:35:59 +01005079#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01005080#define set_beep_amp(spec, nid, idx, dir) \
5081 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
Takashi Iwai67d634c2009-11-16 15:35:59 +01005082#else
5083#define set_beep_amp(spec, nid, idx, dir) /* NOP */
5084#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01005085
5086/*
5087 * OK, here we have finally the patch for ALC880
5088 */
5089
Linus Torvalds1da177e2005-04-16 15:20:36 -07005090static int patch_alc880(struct hda_codec *codec)
5091{
5092 struct alc_spec *spec;
5093 int board_config;
Kailang Yangdf694da2005-12-05 19:42:22 +01005094 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095
Takashi Iwaie560d8d2005-09-09 14:21:46 +02005096 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097 if (spec == NULL)
5098 return -ENOMEM;
5099
5100 codec->spec = spec;
5101
Takashi Iwaif5fcc132006-11-24 17:07:44 +01005102 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
5103 alc880_models,
5104 alc880_cfg_tbl);
5105 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005106 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5107 codec->chip_name);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005108 board_config = ALC880_AUTO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109 }
5110
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005111 if (board_config == ALC880_AUTO) {
5112 /* automatic parse from the BIOS config */
5113 err = alc880_parse_auto_config(codec);
5114 if (err < 0) {
5115 alc_free(codec);
5116 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005117 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02005118 printk(KERN_INFO
5119 "hda_codec: Cannot set up configuration "
5120 "from BIOS. Using 3-stack mode...\n");
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005121 board_config = ALC880_3ST;
5122 }
5123 }
5124
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09005125 err = snd_hda_attach_beep_device(codec, 0x1);
5126 if (err < 0) {
5127 alc_free(codec);
5128 return err;
5129 }
5130
Kailang Yangdf694da2005-12-05 19:42:22 +01005131 if (board_config != ALC880_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005132 setup_preset(codec, &alc880_presets[board_config]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133
Linus Torvalds1da177e2005-04-16 15:20:36 -07005134 spec->stream_analog_playback = &alc880_pcm_analog_playback;
5135 spec->stream_analog_capture = &alc880_pcm_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +01005136 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138 spec->stream_digital_playback = &alc880_pcm_digital_playback;
5139 spec->stream_digital_capture = &alc880_pcm_digital_capture;
5140
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005141 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005142 /* check whether NID 0x07 is valid */
Takashi Iwai54d17402005-11-21 16:33:22 +01005143 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005144 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +02005145 wcap = get_wcaps_type(wcap);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005146 if (wcap != AC_WID_AUD_IN) {
5147 spec->adc_nids = alc880_adc_nids_alt;
5148 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005149 } else {
5150 spec->adc_nids = alc880_adc_nids;
5151 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005152 }
5153 }
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005154 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01005155 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156
Takashi Iwai2134ea42008-01-10 16:53:55 +01005157 spec->vmaster_nid = 0x0c;
5158
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159 codec->patch_ops = alc_patch_ops;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005160 if (board_config == ALC880_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01005161 spec->init_hook = alc880_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +02005162#ifdef CONFIG_SND_HDA_POWER_SAVE
5163 if (!spec->loopback.amplist)
5164 spec->loopback.amplist = alc880_loopbacks;
5165#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005166
5167 return 0;
5168}
5169
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005170
Linus Torvalds1da177e2005-04-16 15:20:36 -07005171/*
5172 * ALC260 support
5173 */
5174
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005175static hda_nid_t alc260_dac_nids[1] = {
5176 /* front */
5177 0x02,
5178};
5179
5180static hda_nid_t alc260_adc_nids[1] = {
5181 /* ADC0 */
5182 0x04,
5183};
5184
Kailang Yangdf694da2005-12-05 19:42:22 +01005185static hda_nid_t alc260_adc_nids_alt[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005186 /* ADC1 */
5187 0x05,
5188};
5189
Jonathan Woithed57fdac2006-02-28 11:38:35 +01005190/* NIDs used when simultaneous access to both ADCs makes sense. Note that
5191 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
5192 */
5193static hda_nid_t alc260_dual_adc_nids[2] = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005194 /* ADC0, ADC1 */
5195 0x04, 0x05
5196};
5197
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005198#define ALC260_DIGOUT_NID 0x03
5199#define ALC260_DIGIN_NID 0x06
5200
5201static struct hda_input_mux alc260_capture_source = {
5202 .num_items = 4,
5203 .items = {
5204 { "Mic", 0x0 },
5205 { "Front Mic", 0x1 },
5206 { "Line", 0x2 },
5207 { "CD", 0x4 },
5208 },
5209};
5210
Jonathan Woithe17e7aec2006-02-28 11:35:18 +01005211/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005212 * headphone jack and the internal CD lines since these are the only pins at
5213 * which audio can appear. For flexibility, also allow the option of
5214 * recording the mixer output on the second ADC (ADC0 doesn't have a
5215 * connection to the mixer output).
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005216 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005217static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
5218 {
5219 .num_items = 3,
5220 .items = {
5221 { "Mic/Line", 0x0 },
5222 { "CD", 0x4 },
5223 { "Headphone", 0x2 },
5224 },
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005225 },
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005226 {
5227 .num_items = 4,
5228 .items = {
5229 { "Mic/Line", 0x0 },
5230 { "CD", 0x4 },
5231 { "Headphone", 0x2 },
5232 { "Mixer", 0x5 },
5233 },
5234 },
5235
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005236};
5237
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005238/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
5239 * the Fujitsu S702x, but jacks are marked differently.
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005240 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005241static struct hda_input_mux alc260_acer_capture_sources[2] = {
5242 {
5243 .num_items = 4,
5244 .items = {
5245 { "Mic", 0x0 },
5246 { "Line", 0x2 },
5247 { "CD", 0x4 },
5248 { "Headphone", 0x5 },
5249 },
5250 },
5251 {
5252 .num_items = 5,
5253 .items = {
5254 { "Mic", 0x0 },
5255 { "Line", 0x2 },
5256 { "CD", 0x4 },
5257 { "Headphone", 0x6 },
5258 { "Mixer", 0x5 },
5259 },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005260 },
5261};
Michael Schwingencc959482009-02-22 18:58:45 +01005262
5263/* Maxdata Favorit 100XS */
5264static struct hda_input_mux alc260_favorit100_capture_sources[2] = {
5265 {
5266 .num_items = 2,
5267 .items = {
5268 { "Line/Mic", 0x0 },
5269 { "CD", 0x4 },
5270 },
5271 },
5272 {
5273 .num_items = 3,
5274 .items = {
5275 { "Line/Mic", 0x0 },
5276 { "CD", 0x4 },
5277 { "Mixer", 0x5 },
5278 },
5279 },
5280};
5281
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282/*
5283 * This is just place-holder, so there's something for alc_build_pcms to look
5284 * at when it calculates the maximum number of channels. ALC260 has no mixer
5285 * element which allows changing the channel mode, so the verb list is
5286 * never used.
5287 */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01005288static struct hda_channel_mode alc260_modes[1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005289 { 2, NULL },
5290};
5291
Kailang Yangdf694da2005-12-05 19:42:22 +01005292
5293/* Mixer combinations
5294 *
5295 * basic: base_output + input + pc_beep + capture
5296 * HP: base_output + input + capture_alt
5297 * HP_3013: hp_3013 + input + capture
5298 * fujitsu: fujitsu + capture
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005299 * acer: acer + capture
Kailang Yangdf694da2005-12-05 19:42:22 +01005300 */
5301
5302static struct snd_kcontrol_new alc260_base_output_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02005303 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01005304 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01005305 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5306 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
5307 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
5308 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
5309 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005310};
Kailang Yangdf694da2005-12-05 19:42:22 +01005311
5312static struct snd_kcontrol_new alc260_input_mixer[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005313 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5314 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5315 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5316 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5317 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5318 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5319 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
5320 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321 { } /* end */
5322};
5323
Takashi Iwaibec15c32008-01-28 18:16:30 +01005324/* update HP, line and mono out pins according to the master switch */
5325static void alc260_hp_master_update(struct hda_codec *codec,
5326 hda_nid_t hp, hda_nid_t line,
5327 hda_nid_t mono)
5328{
5329 struct alc_spec *spec = codec->spec;
5330 unsigned int val = spec->master_sw ? PIN_HP : 0;
5331 /* change HP and line-out pins */
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005332 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005333 val);
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005334 snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005335 val);
5336 /* mono (speaker) depending on the HP jack sense */
5337 val = (val && !spec->jack_present) ? PIN_OUT : 0;
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005338 snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005339 val);
5340}
5341
5342static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
5343 struct snd_ctl_elem_value *ucontrol)
5344{
5345 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5346 struct alc_spec *spec = codec->spec;
5347 *ucontrol->value.integer.value = spec->master_sw;
5348 return 0;
5349}
5350
5351static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
5352 struct snd_ctl_elem_value *ucontrol)
5353{
5354 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5355 struct alc_spec *spec = codec->spec;
5356 int val = !!*ucontrol->value.integer.value;
5357 hda_nid_t hp, line, mono;
5358
5359 if (val == spec->master_sw)
5360 return 0;
5361 spec->master_sw = val;
5362 hp = (kcontrol->private_value >> 16) & 0xff;
5363 line = (kcontrol->private_value >> 8) & 0xff;
5364 mono = kcontrol->private_value & 0xff;
5365 alc260_hp_master_update(codec, hp, line, mono);
5366 return 1;
5367}
5368
5369static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
5370 {
5371 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5372 .name = "Master Playback Switch",
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01005373 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005374 .info = snd_ctl_boolean_mono_info,
5375 .get = alc260_hp_master_sw_get,
5376 .put = alc260_hp_master_sw_put,
5377 .private_value = (0x0f << 16) | (0x10 << 8) | 0x11
5378 },
5379 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5380 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
5381 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5382 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
5383 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
5384 HDA_OUTPUT),
5385 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
5386 { } /* end */
5387};
5388
5389static struct hda_verb alc260_hp_unsol_verbs[] = {
5390 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5391 {},
5392};
5393
5394static void alc260_hp_automute(struct hda_codec *codec)
5395{
5396 struct alc_spec *spec = codec->spec;
Takashi Iwaibec15c32008-01-28 18:16:30 +01005397
Wu Fengguang864f92b2009-11-18 12:38:02 +08005398 spec->jack_present = snd_hda_jack_detect(codec, 0x10);
Takashi Iwaibec15c32008-01-28 18:16:30 +01005399 alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
5400}
5401
5402static void alc260_hp_unsol_event(struct hda_codec *codec, unsigned int res)
5403{
5404 if ((res >> 26) == ALC880_HP_EVENT)
5405 alc260_hp_automute(codec);
5406}
5407
Kailang Yangdf694da2005-12-05 19:42:22 +01005408static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
Takashi Iwaibec15c32008-01-28 18:16:30 +01005409 {
5410 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5411 .name = "Master Playback Switch",
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01005412 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005413 .info = snd_ctl_boolean_mono_info,
5414 .get = alc260_hp_master_sw_get,
5415 .put = alc260_hp_master_sw_put,
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005416 .private_value = (0x15 << 16) | (0x10 << 8) | 0x11
Takashi Iwaibec15c32008-01-28 18:16:30 +01005417 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005418 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5419 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
5420 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
5421 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
5422 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5423 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +01005424 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
5425 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02005426 { } /* end */
5427};
5428
Kailang Yang3f878302008-08-26 13:02:23 +02005429static struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
5430 .ops = &snd_hda_bind_vol,
5431 .values = {
5432 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
5433 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
5434 HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT),
5435 0
5436 },
5437};
5438
5439static struct hda_bind_ctls alc260_dc7600_bind_switch = {
5440 .ops = &snd_hda_bind_sw,
5441 .values = {
5442 HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
5443 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
5444 0
5445 },
5446};
5447
5448static struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
5449 HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
5450 HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
5451 HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
5452 HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
5453 { } /* end */
5454};
5455
Takashi Iwaibec15c32008-01-28 18:16:30 +01005456static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
5457 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5458 {},
5459};
5460
5461static void alc260_hp_3013_automute(struct hda_codec *codec)
5462{
5463 struct alc_spec *spec = codec->spec;
Takashi Iwaibec15c32008-01-28 18:16:30 +01005464
Wu Fengguang864f92b2009-11-18 12:38:02 +08005465 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005466 alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
Takashi Iwaibec15c32008-01-28 18:16:30 +01005467}
5468
5469static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
5470 unsigned int res)
5471{
5472 if ((res >> 26) == ALC880_HP_EVENT)
5473 alc260_hp_3013_automute(codec);
5474}
5475
Kailang Yang3f878302008-08-26 13:02:23 +02005476static void alc260_hp_3012_automute(struct hda_codec *codec)
5477{
Wu Fengguang864f92b2009-11-18 12:38:02 +08005478 unsigned int bits = snd_hda_jack_detect(codec, 0x10) ? 0 : PIN_OUT;
Kailang Yang3f878302008-08-26 13:02:23 +02005479
Kailang Yang3f878302008-08-26 13:02:23 +02005480 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5481 bits);
5482 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5483 bits);
5484 snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5485 bits);
5486}
5487
5488static void alc260_hp_3012_unsol_event(struct hda_codec *codec,
5489 unsigned int res)
5490{
5491 if ((res >> 26) == ALC880_HP_EVENT)
5492 alc260_hp_3012_automute(codec);
5493}
5494
5495/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005496 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
5497 */
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01005498static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005499 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01005500 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005501 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005502 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5503 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5504 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
5505 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005506 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005507 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5508 HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01005509 { } /* end */
5510};
5511
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005512/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
5513 * versions of the ALC260 don't act on requests to enable mic bias from NID
5514 * 0x0f (used to drive the headphone jack in these laptops). The ALC260
5515 * datasheet doesn't mention this restriction. At this stage it's not clear
5516 * whether this behaviour is intentional or is a hardware bug in chip
5517 * revisions available in early 2006. Therefore for now allow the
5518 * "Headphone Jack Mode" control to span all choices, but if it turns out
5519 * that the lack of mic bias for this NID is intentional we could change the
5520 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
5521 *
5522 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
5523 * don't appear to make the mic bias available from the "line" jack, even
5524 * though the NID used for this jack (0x14) can supply it. The theory is
5525 * that perhaps Acer have included blocking capacitors between the ALC260
5526 * and the output jack. If this turns out to be the case for all such
5527 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
5528 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
Jonathan Woithebd869482006-11-28 11:35:52 +01005529 *
5530 * The C20x Tablet series have a mono internal speaker which is controlled
5531 * via the chip's Mono sum widget and pin complex, so include the necessary
5532 * controls for such models. On models without a "mono speaker" the control
5533 * won't do anything.
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005534 */
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005535static struct snd_kcontrol_new alc260_acer_mixer[] = {
5536 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5537 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005538 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005539 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
Jonathan Woithebd869482006-11-28 11:35:52 +01005540 HDA_OUTPUT),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005541 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
Jonathan Woithebd869482006-11-28 11:35:52 +01005542 HDA_INPUT),
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005543 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5544 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5545 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5546 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5547 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5548 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5549 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5550 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005551 { } /* end */
5552};
5553
Michael Schwingencc959482009-02-22 18:58:45 +01005554/* Maxdata Favorit 100XS: one output and one input (0x12) jack
5555 */
5556static struct snd_kcontrol_new alc260_favorit100_mixer[] = {
5557 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5558 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
5559 ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
5560 HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5561 HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5562 ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5563 { } /* end */
5564};
5565
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005566/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
5567 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
5568 */
5569static struct snd_kcontrol_new alc260_will_mixer[] = {
5570 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5571 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
5572 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5573 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5574 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5575 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5576 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5577 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
5578 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5579 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005580 { } /* end */
5581};
5582
5583/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
5584 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
5585 */
5586static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
5587 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5588 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
5589 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5590 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5591 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5592 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
5593 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
5594 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5595 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5596 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
5597 { } /* end */
5598};
5599
Kailang Yangdf694da2005-12-05 19:42:22 +01005600/*
5601 * initialization verbs
5602 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005603static struct hda_verb alc260_init_verbs[] = {
5604 /* Line In pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02005605 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606 /* CD pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02005607 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005608 /* Mic1 (rear panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02005609 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610 /* Mic2 (front panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02005611 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005612 /* LINE-2 is used for line-out in rear */
Takashi Iwai05acb862005-06-10 19:50:25 +02005613 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005614 /* select line-out */
Jonathan Woithefd56f2d2006-01-24 10:35:46 +01005615 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005616 /* LINE-OUT pin */
Takashi Iwai05acb862005-06-10 19:50:25 +02005617 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005618 /* enable HP */
Takashi Iwai05acb862005-06-10 19:50:25 +02005619 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620 /* enable Mono */
Takashi Iwai05acb862005-06-10 19:50:25 +02005621 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5622 /* mute capture amp left and right */
Takashi Iwai16ded522005-06-10 19:58:24 +02005623 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624 /* set connection select to line in (default select for this ADC) */
5625 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai16ded522005-06-10 19:58:24 +02005626 /* mute capture amp left and right */
5627 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5628 /* set connection select to line in (default select for this ADC) */
5629 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai05acb862005-06-10 19:50:25 +02005630 /* set vol=0 Line-Out mixer amp left and right */
5631 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5632 /* unmute pin widget amp left and right (no gain on this amp) */
5633 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5634 /* set vol=0 HP mixer amp left and right */
5635 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5636 /* unmute pin widget amp left and right (no gain on this amp) */
5637 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5638 /* set vol=0 Mono mixer amp left and right */
5639 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5640 /* unmute pin widget amp left and right (no gain on this amp) */
5641 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5642 /* unmute LINE-2 out pin */
5643 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005644 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
5645 * Line In 2 = 0x03
5646 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02005647 /* mute analog inputs */
5648 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5649 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5650 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5651 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5652 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005653 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
Takashi Iwai05acb862005-06-10 19:50:25 +02005654 /* mute Front out path */
5655 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5656 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5657 /* mute Headphone out path */
5658 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5659 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5660 /* mute Mono out path */
5661 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5662 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663 { }
5664};
5665
Takashi Iwai474167d2006-05-17 17:17:43 +02005666#if 0 /* should be identical with alc260_init_verbs? */
Kailang Yangdf694da2005-12-05 19:42:22 +01005667static struct hda_verb alc260_hp_init_verbs[] = {
5668 /* Headphone and output */
5669 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
5670 /* mono output */
5671 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5672 /* Mic1 (rear panel) pin widget for input and vref at 80% */
5673 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5674 /* Mic2 (front panel) pin widget for input and vref at 80% */
5675 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5676 /* Line In pin widget for input */
5677 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5678 /* Line-2 pin widget for output */
5679 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5680 /* CD pin widget for input */
5681 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5682 /* unmute amp left and right */
5683 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
5684 /* set connection select to line in (default select for this ADC) */
5685 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
5686 /* unmute Line-Out mixer amp left and right (volume = 0) */
5687 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5688 /* mute pin widget amp left and right (no gain on this amp) */
5689 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5690 /* unmute HP mixer amp left and right (volume = 0) */
5691 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5692 /* mute pin widget amp left and right (no gain on this amp) */
5693 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005694 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
5695 * Line In 2 = 0x03
5696 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02005697 /* mute analog inputs */
5698 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5699 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5700 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5701 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5702 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01005703 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
5704 /* Unmute Front out path */
5705 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5706 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5707 /* Unmute Headphone out path */
5708 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5709 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5710 /* Unmute Mono out path */
5711 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5712 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5713 { }
5714};
Takashi Iwai474167d2006-05-17 17:17:43 +02005715#endif
Kailang Yangdf694da2005-12-05 19:42:22 +01005716
5717static struct hda_verb alc260_hp_3013_init_verbs[] = {
5718 /* Line out and output */
5719 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5720 /* mono output */
5721 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5722 /* Mic1 (rear panel) pin widget for input and vref at 80% */
5723 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5724 /* Mic2 (front panel) pin widget for input and vref at 80% */
5725 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5726 /* Line In pin widget for input */
5727 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5728 /* Headphone pin widget for output */
5729 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
5730 /* CD pin widget for input */
5731 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5732 /* unmute amp left and right */
5733 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
5734 /* set connection select to line in (default select for this ADC) */
5735 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
5736 /* unmute Line-Out mixer amp left and right (volume = 0) */
5737 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5738 /* mute pin widget amp left and right (no gain on this amp) */
5739 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5740 /* unmute HP mixer amp left and right (volume = 0) */
5741 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5742 /* mute pin widget amp left and right (no gain on this amp) */
5743 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005744 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
5745 * Line In 2 = 0x03
5746 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02005747 /* mute analog inputs */
5748 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5749 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5750 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5751 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5752 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01005753 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
5754 /* Unmute Front out path */
5755 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5756 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5757 /* Unmute Headphone out path */
5758 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5759 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5760 /* Unmute Mono out path */
5761 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5762 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5763 { }
5764};
5765
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005766/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005767 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
5768 * audio = 0x16, internal speaker = 0x10.
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005769 */
5770static struct hda_verb alc260_fujitsu_init_verbs[] = {
5771 /* Disable all GPIOs */
5772 {0x01, AC_VERB_SET_GPIO_MASK, 0},
5773 /* Internal speaker is connected to headphone pin */
5774 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5775 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
5776 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Jonathan Woithef7ace402006-02-28 11:46:14 +01005777 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
5778 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5779 /* Ensure all other unused pins are disabled and muted. */
5780 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5781 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005782 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
Jonathan Woithef7ace402006-02-28 11:46:14 +01005783 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005784 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
Jonathan Woithef7ace402006-02-28 11:46:14 +01005785 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5786 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5787 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005788
Jonathan Woithef7ace402006-02-28 11:46:14 +01005789 /* Disable digital (SPDIF) pins */
5790 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
5791 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005792
Kailang Yangea1fb292008-08-26 12:58:38 +02005793 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
Jonathan Woithef7ace402006-02-28 11:46:14 +01005794 * when acting as an output.
5795 */
5796 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
5797
5798 /* Start with output sum widgets muted and their output gains at min */
Takashi Iwai8b33a5a2006-02-09 11:57:01 +01005799 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5800 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5801 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5802 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5803 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5804 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5805 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5806 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5807 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005808
Jonathan Woithef7ace402006-02-28 11:46:14 +01005809 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
5810 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5811 /* Unmute Line1 pin widget output buffer since it starts as an output.
5812 * If the pin mode is changed by the user the pin mode control will
5813 * take care of enabling the pin's input/output buffers as needed.
5814 * Therefore there's no need to enable the input buffer at this
5815 * stage.
Jonathan Woithecdcd9262006-02-28 11:36:42 +01005816 */
Jonathan Woithef7ace402006-02-28 11:46:14 +01005817 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +02005818 /* Unmute input buffer of pin widget used for Line-in (no equiv
Jonathan Woithecdcd9262006-02-28 11:36:42 +01005819 * mixer ctrl)
5820 */
Jonathan Woithef7ace402006-02-28 11:46:14 +01005821 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005822
Jonathan Woithef7ace402006-02-28 11:46:14 +01005823 /* Mute capture amp left and right */
5824 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +02005825 /* Set ADC connection select to match default mixer setting - line
Jonathan Woithef7ace402006-02-28 11:46:14 +01005826 * in (on mic1 pin)
5827 */
5828 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005829
Jonathan Woithef7ace402006-02-28 11:46:14 +01005830 /* Do the same for the second ADC: mute capture input amp and
5831 * set ADC connection to line in (on mic1 pin)
5832 */
5833 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5834 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005835
Jonathan Woithef7ace402006-02-28 11:46:14 +01005836 /* Mute all inputs to mixer widget (even unconnected ones) */
5837 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
5838 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
5839 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
5840 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
5841 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
5842 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
5843 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
5844 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
Takashi Iwai4a471b72005-12-07 13:56:29 +01005845
5846 { }
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005847};
5848
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005849/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
5850 * similar laptops (adapted from Fujitsu init verbs).
5851 */
5852static struct hda_verb alc260_acer_init_verbs[] = {
5853 /* On TravelMate laptops, GPIO 0 enables the internal speaker and
5854 * the headphone jack. Turn this on and rely on the standard mute
5855 * methods whenever the user wants to turn these outputs off.
5856 */
5857 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
5858 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5859 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5860 /* Internal speaker/Headphone jack is connected to Line-out pin */
5861 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5862 /* Internal microphone/Mic jack is connected to Mic1 pin */
5863 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
5864 /* Line In jack is connected to Line1 pin */
5865 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Jonathan Woithebd869482006-11-28 11:35:52 +01005866 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
5867 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005868 /* Ensure all other unused pins are disabled and muted. */
5869 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5870 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005871 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5872 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5873 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5874 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5875 /* Disable digital (SPDIF) pins */
5876 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
5877 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
5878
Kailang Yangea1fb292008-08-26 12:58:38 +02005879 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005880 * bus when acting as outputs.
5881 */
5882 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
5883 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
5884
5885 /* Start with output sum widgets muted and their output gains at min */
5886 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5887 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5888 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5889 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5890 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5891 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5892 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5893 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5894 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5895
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005896 /* Unmute Line-out pin widget amp left and right
5897 * (no equiv mixer ctrl)
5898 */
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005899 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Jonathan Woithebd869482006-11-28 11:35:52 +01005900 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
5901 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005902 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
5903 * inputs. If the pin mode is changed by the user the pin mode control
5904 * will take care of enabling the pin's input/output buffers as needed.
5905 * Therefore there's no need to enable the input buffer at this
5906 * stage.
5907 */
5908 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5909 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5910
5911 /* Mute capture amp left and right */
5912 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5913 /* Set ADC connection select to match default mixer setting - mic
5914 * (on mic1 pin)
5915 */
5916 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
5917
5918 /* Do similar with the second ADC: mute capture input amp and
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005919 * set ADC connection to mic to match ALSA's default state.
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005920 */
5921 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005922 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005923
5924 /* Mute all inputs to mixer widget (even unconnected ones) */
5925 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
5926 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
5927 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
5928 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
5929 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
5930 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
5931 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
5932 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
5933
5934 { }
5935};
5936
Michael Schwingencc959482009-02-22 18:58:45 +01005937/* Initialisation sequence for Maxdata Favorit 100XS
5938 * (adapted from Acer init verbs).
5939 */
5940static struct hda_verb alc260_favorit100_init_verbs[] = {
5941 /* GPIO 0 enables the output jack.
5942 * Turn this on and rely on the standard mute
5943 * methods whenever the user wants to turn these outputs off.
5944 */
5945 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
5946 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5947 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5948 /* Line/Mic input jack is connected to Mic1 pin */
5949 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
5950 /* Ensure all other unused pins are disabled and muted. */
5951 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5952 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5953 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5954 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5955 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5956 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5957 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5958 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5959 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5960 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5961 /* Disable digital (SPDIF) pins */
5962 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
5963 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
5964
5965 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
5966 * bus when acting as outputs.
5967 */
5968 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
5969 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
5970
5971 /* Start with output sum widgets muted and their output gains at min */
5972 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5973 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5974 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5975 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5976 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5977 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5978 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5979 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5980 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5981
5982 /* Unmute Line-out pin widget amp left and right
5983 * (no equiv mixer ctrl)
5984 */
5985 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5986 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
5987 * inputs. If the pin mode is changed by the user the pin mode control
5988 * will take care of enabling the pin's input/output buffers as needed.
5989 * Therefore there's no need to enable the input buffer at this
5990 * stage.
5991 */
5992 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5993
5994 /* Mute capture amp left and right */
5995 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5996 /* Set ADC connection select to match default mixer setting - mic
5997 * (on mic1 pin)
5998 */
5999 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6000
6001 /* Do similar with the second ADC: mute capture input amp and
6002 * set ADC connection to mic to match ALSA's default state.
6003 */
6004 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6005 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6006
6007 /* Mute all inputs to mixer widget (even unconnected ones) */
6008 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6009 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6010 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6011 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6012 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6013 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6014 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6015 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6016
6017 { }
6018};
6019
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006020static struct hda_verb alc260_will_verbs[] = {
6021 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6022 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
6023 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
6024 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
6025 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
6026 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
6027 {}
6028};
6029
6030static struct hda_verb alc260_replacer_672v_verbs[] = {
6031 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
6032 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
6033 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
6034
6035 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6036 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6037 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
6038
6039 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6040 {}
6041};
6042
6043/* toggle speaker-output according to the hp-jack state */
6044static void alc260_replacer_672v_automute(struct hda_codec *codec)
6045{
6046 unsigned int present;
6047
6048 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
Wu Fengguang864f92b2009-11-18 12:38:02 +08006049 present = snd_hda_jack_detect(codec, 0x0f);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006050 if (present) {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02006051 snd_hda_codec_write_cache(codec, 0x01, 0,
6052 AC_VERB_SET_GPIO_DATA, 1);
6053 snd_hda_codec_write_cache(codec, 0x0f, 0,
6054 AC_VERB_SET_PIN_WIDGET_CONTROL,
6055 PIN_HP);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006056 } else {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02006057 snd_hda_codec_write_cache(codec, 0x01, 0,
6058 AC_VERB_SET_GPIO_DATA, 0);
6059 snd_hda_codec_write_cache(codec, 0x0f, 0,
6060 AC_VERB_SET_PIN_WIDGET_CONTROL,
6061 PIN_OUT);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006062 }
6063}
6064
6065static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
6066 unsigned int res)
6067{
6068 if ((res >> 26) == ALC880_HP_EVENT)
6069 alc260_replacer_672v_automute(codec);
6070}
6071
Kailang Yang3f878302008-08-26 13:02:23 +02006072static struct hda_verb alc260_hp_dc7600_verbs[] = {
6073 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
6074 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
6075 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6076 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6077 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6078 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6079 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6080 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6081 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6082 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6083 {}
6084};
6085
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006086/* Test configuration for debugging, modelled after the ALC880 test
6087 * configuration.
6088 */
6089#ifdef CONFIG_SND_DEBUG
6090static hda_nid_t alc260_test_dac_nids[1] = {
6091 0x02,
6092};
6093static hda_nid_t alc260_test_adc_nids[2] = {
6094 0x04, 0x05,
6095};
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006096/* For testing the ALC260, each input MUX needs its own definition since
Kailang Yangea1fb292008-08-26 12:58:38 +02006097 * the signal assignments are different. This assumes that the first ADC
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006098 * is NID 0x04.
Jonathan Woithe17e7aec2006-02-28 11:35:18 +01006099 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006100static struct hda_input_mux alc260_test_capture_sources[2] = {
6101 {
6102 .num_items = 7,
6103 .items = {
6104 { "MIC1 pin", 0x0 },
6105 { "MIC2 pin", 0x1 },
6106 { "LINE1 pin", 0x2 },
6107 { "LINE2 pin", 0x3 },
6108 { "CD pin", 0x4 },
6109 { "LINE-OUT pin", 0x5 },
6110 { "HP-OUT pin", 0x6 },
6111 },
6112 },
6113 {
6114 .num_items = 8,
6115 .items = {
6116 { "MIC1 pin", 0x0 },
6117 { "MIC2 pin", 0x1 },
6118 { "LINE1 pin", 0x2 },
6119 { "LINE2 pin", 0x3 },
6120 { "CD pin", 0x4 },
6121 { "Mixer", 0x5 },
6122 { "LINE-OUT pin", 0x6 },
6123 { "HP-OUT pin", 0x7 },
6124 },
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006125 },
6126};
6127static struct snd_kcontrol_new alc260_test_mixer[] = {
6128 /* Output driver widgets */
6129 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
6130 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
6131 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6132 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
6133 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6134 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
6135
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006136 /* Modes for retasking pin widgets
6137 * Note: the ALC260 doesn't seem to act on requests to enable mic
6138 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
6139 * mention this restriction. At this stage it's not clear whether
6140 * this behaviour is intentional or is a hardware bug in chip
6141 * revisions available at least up until early 2006. Therefore for
6142 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
6143 * choices, but if it turns out that the lack of mic bias for these
6144 * NIDs is intentional we could change their modes from
6145 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
6146 */
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006147 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
6148 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
6149 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
6150 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
6151 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
6152 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
6153
6154 /* Loopback mixer controls */
6155 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
6156 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
6157 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
6158 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
6159 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
6160 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
6161 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
6162 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
6163 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6164 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006165 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
6166 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
6167 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
6168 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
Jonathan Woithe5c8f8582006-02-28 11:43:27 +01006169
6170 /* Controls for GPIO pins, assuming they are configured as outputs */
6171 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
6172 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
6173 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
6174 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
6175
Jonathan Woithe92621f12006-02-28 11:47:47 +01006176 /* Switches to allow the digital IO pins to be enabled. The datasheet
6177 * is ambigious as to which NID is which; testing on laptops which
Kailang Yangea1fb292008-08-26 12:58:38 +02006178 * make this output available should provide clarification.
Jonathan Woithe92621f12006-02-28 11:47:47 +01006179 */
6180 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
6181 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
6182
Jonathan Woithef8225f62008-01-08 12:16:54 +01006183 /* A switch allowing EAPD to be enabled. Some laptops seem to use
6184 * this output to turn on an external amplifier.
6185 */
6186 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
6187 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
6188
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006189 { } /* end */
6190};
6191static struct hda_verb alc260_test_init_verbs[] = {
Jonathan Woithe5c8f8582006-02-28 11:43:27 +01006192 /* Enable all GPIOs as outputs with an initial value of 0 */
6193 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
6194 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
6195 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
6196
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006197 /* Enable retasking pins as output, initially without power amp */
6198 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6199 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6200 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6201 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6202 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6203 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6204
Jonathan Woithe92621f12006-02-28 11:47:47 +01006205 /* Disable digital (SPDIF) pins initially, but users can enable
6206 * them via a mixer switch. In the case of SPDIF-out, this initverb
6207 * payload also sets the generation to 0, output to be in "consumer"
6208 * PCM format, copyright asserted, no pre-emphasis and no validity
6209 * control.
6210 */
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006211 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6212 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6213
Kailang Yangea1fb292008-08-26 12:58:38 +02006214 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006215 * OUT1 sum bus when acting as an output.
6216 */
6217 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6218 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
6219 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6220 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
6221
6222 /* Start with output sum widgets muted and their output gains at min */
6223 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6224 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6225 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6226 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6227 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6228 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6229 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6230 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6231 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6232
Jonathan Woithecdcd9262006-02-28 11:36:42 +01006233 /* Unmute retasking pin widget output buffers since the default
6234 * state appears to be output. As the pin mode is changed by the
6235 * user the pin mode control will take care of enabling the pin's
6236 * input/output buffers as needed.
6237 */
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006238 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6239 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6240 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6241 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6242 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6243 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6244 /* Also unmute the mono-out pin widget */
6245 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6246
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006247 /* Mute capture amp left and right */
6248 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithef7ace402006-02-28 11:46:14 +01006249 /* Set ADC connection select to match default mixer setting (mic1
6250 * pin)
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006251 */
6252 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6253
6254 /* Do the same for the second ADC: mute capture input amp and
Jonathan Woithef7ace402006-02-28 11:46:14 +01006255 * set ADC connection to mic1 pin
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006256 */
6257 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6258 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6259
6260 /* Mute all inputs to mixer widget (even unconnected ones) */
6261 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6262 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6263 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6264 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6265 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6266 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6267 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6268 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6269
6270 { }
6271};
6272#endif
6273
Takashi Iwai63300792008-01-24 15:31:36 +01006274#define alc260_pcm_analog_playback alc880_pcm_analog_alt_playback
6275#define alc260_pcm_analog_capture alc880_pcm_analog_capture
Linus Torvalds1da177e2005-04-16 15:20:36 -07006276
Takashi Iwaia3bcba32005-12-06 19:05:29 +01006277#define alc260_pcm_digital_playback alc880_pcm_digital_playback
6278#define alc260_pcm_digital_capture alc880_pcm_digital_capture
6279
Kailang Yangdf694da2005-12-05 19:42:22 +01006280/*
6281 * for BIOS auto-configuration
6282 */
6283
6284static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
Takashi Iwai863b4512008-10-21 17:01:47 +02006285 const char *pfx, int *vol_bits)
Kailang Yangdf694da2005-12-05 19:42:22 +01006286{
6287 hda_nid_t nid_vol;
6288 unsigned long vol_val, sw_val;
Kailang Yangdf694da2005-12-05 19:42:22 +01006289 int err;
6290
6291 if (nid >= 0x0f && nid < 0x11) {
6292 nid_vol = nid - 0x7;
6293 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
6294 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
6295 } else if (nid == 0x11) {
6296 nid_vol = nid - 0x7;
6297 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
6298 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
6299 } else if (nid >= 0x12 && nid <= 0x15) {
6300 nid_vol = 0x08;
6301 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
6302 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
6303 } else
6304 return 0; /* N/A */
Kailang Yangea1fb292008-08-26 12:58:38 +02006305
Takashi Iwai863b4512008-10-21 17:01:47 +02006306 if (!(*vol_bits & (1 << nid_vol))) {
6307 /* first control for the volume widget */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02006308 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
Takashi Iwai863b4512008-10-21 17:01:47 +02006309 if (err < 0)
6310 return err;
6311 *vol_bits |= (1 << nid_vol);
6312 }
Takashi Iwai0afe5f82009-10-02 09:20:00 +02006313 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006314 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006315 return err;
6316 return 1;
6317}
6318
6319/* add playback controls from the parsed DAC table */
6320static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
6321 const struct auto_pin_cfg *cfg)
6322{
6323 hda_nid_t nid;
6324 int err;
Takashi Iwai863b4512008-10-21 17:01:47 +02006325 int vols = 0;
Kailang Yangdf694da2005-12-05 19:42:22 +01006326
6327 spec->multiout.num_dacs = 1;
6328 spec->multiout.dac_nids = spec->private_dac_nids;
6329 spec->multiout.dac_nids[0] = 0x02;
6330
6331 nid = cfg->line_out_pins[0];
6332 if (nid) {
Takashi Iwai23112d62009-08-25 16:07:08 +02006333 const char *pfx;
6334 if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
6335 pfx = "Master";
6336 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
6337 pfx = "Speaker";
6338 else
6339 pfx = "Front";
6340 err = alc260_add_playback_controls(spec, nid, pfx, &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006341 if (err < 0)
6342 return err;
6343 }
6344
Takashi Iwai82bc9552006-03-21 11:24:42 +01006345 nid = cfg->speaker_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006346 if (nid) {
Takashi Iwai863b4512008-10-21 17:01:47 +02006347 err = alc260_add_playback_controls(spec, nid, "Speaker", &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006348 if (err < 0)
6349 return err;
6350 }
6351
Takashi Iwaieb06ed82006-09-20 17:10:27 +02006352 nid = cfg->hp_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006353 if (nid) {
Takashi Iwai863b4512008-10-21 17:01:47 +02006354 err = alc260_add_playback_controls(spec, nid, "Headphone",
6355 &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006356 if (err < 0)
6357 return err;
6358 }
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006359 return 0;
Kailang Yangdf694da2005-12-05 19:42:22 +01006360}
6361
6362/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +02006363static int alc260_auto_create_input_ctls(struct hda_codec *codec,
Kailang Yangdf694da2005-12-05 19:42:22 +01006364 const struct auto_pin_cfg *cfg)
6365{
Takashi Iwai05f5f472009-08-25 13:10:18 +02006366 return alc_auto_create_input_ctls(codec, cfg, 0x07, 0x04, 0x05);
Kailang Yangdf694da2005-12-05 19:42:22 +01006367}
6368
6369static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
6370 hda_nid_t nid, int pin_type,
6371 int sel_idx)
6372{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006373 alc_set_pin_output(codec, nid, pin_type);
Kailang Yangdf694da2005-12-05 19:42:22 +01006374 /* need the manual connection? */
6375 if (nid >= 0x12) {
6376 int idx = nid - 0x12;
6377 snd_hda_codec_write(codec, idx + 0x0b, 0,
6378 AC_VERB_SET_CONNECT_SEL, sel_idx);
Kailang Yangdf694da2005-12-05 19:42:22 +01006379 }
6380}
6381
6382static void alc260_auto_init_multi_out(struct hda_codec *codec)
6383{
6384 struct alc_spec *spec = codec->spec;
6385 hda_nid_t nid;
6386
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006387 nid = spec->autocfg.line_out_pins[0];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02006388 if (nid) {
6389 int pin_type = get_pin_type(spec->autocfg.line_out_type);
6390 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
6391 }
Kailang Yangea1fb292008-08-26 12:58:38 +02006392
Takashi Iwai82bc9552006-03-21 11:24:42 +01006393 nid = spec->autocfg.speaker_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006394 if (nid)
6395 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
6396
Takashi Iwaieb06ed82006-09-20 17:10:27 +02006397 nid = spec->autocfg.hp_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006398 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02006399 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006400}
Kailang Yangdf694da2005-12-05 19:42:22 +01006401
6402#define ALC260_PIN_CD_NID 0x16
6403static void alc260_auto_init_analog_input(struct hda_codec *codec)
6404{
6405 struct alc_spec *spec = codec->spec;
6406 int i;
6407
6408 for (i = 0; i < AUTO_PIN_LAST; i++) {
6409 hda_nid_t nid = spec->autocfg.input_pins[i];
6410 if (nid >= 0x12) {
Takashi Iwai23f0c042009-02-26 13:03:58 +01006411 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +01006412 if (nid != ALC260_PIN_CD_NID &&
6413 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006414 snd_hda_codec_write(codec, nid, 0,
6415 AC_VERB_SET_AMP_GAIN_MUTE,
Kailang Yangdf694da2005-12-05 19:42:22 +01006416 AMP_OUT_MUTE);
6417 }
6418 }
6419}
6420
Takashi Iwai7f311a42010-04-09 17:32:23 +02006421#define alc260_auto_init_input_src alc880_auto_init_input_src
6422
Kailang Yangdf694da2005-12-05 19:42:22 +01006423/*
6424 * generic initialization of ADC, input mixers and output mixers
6425 */
6426static struct hda_verb alc260_volume_init_verbs[] = {
6427 /*
6428 * Unmute ADC0-1 and set the default input to mic-in
6429 */
6430 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6431 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6432 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6433 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +02006434
Kailang Yangdf694da2005-12-05 19:42:22 +01006435 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6436 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006437 * Note: PASD motherboards uses the Line In 2 as the input for
6438 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +01006439 */
6440 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02006441 /* mute analog inputs */
6442 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6443 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6444 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6445 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6446 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01006447
6448 /*
6449 * Set up output mixers (0x08 - 0x0a)
6450 */
6451 /* set vol=0 to output mixers */
6452 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6453 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6454 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6455 /* set up input amps for analog loopback */
6456 /* Amp Indices: DAC = 0, mixer = 1 */
6457 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6458 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6459 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6460 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6461 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6462 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +02006463
Kailang Yangdf694da2005-12-05 19:42:22 +01006464 { }
6465};
6466
6467static int alc260_parse_auto_config(struct hda_codec *codec)
6468{
6469 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01006470 int err;
6471 static hda_nid_t alc260_ignore[] = { 0x17, 0 };
6472
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006473 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
6474 alc260_ignore);
6475 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006476 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006477 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
6478 if (err < 0)
Takashi Iwai4a471b72005-12-07 13:56:29 +01006479 return err;
Takashi Iwai603c4012008-07-30 15:01:44 +02006480 if (!spec->kctls.list)
Kailang Yangdf694da2005-12-05 19:42:22 +01006481 return 0; /* can't find valid BIOS pin config */
Takashi Iwai05f5f472009-08-25 13:10:18 +02006482 err = alc260_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006483 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006484 return err;
6485
6486 spec->multiout.max_channels = 2;
6487
Takashi Iwai0852d7a2009-02-11 11:35:15 +01006488 if (spec->autocfg.dig_outs)
Kailang Yangdf694da2005-12-05 19:42:22 +01006489 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
Takashi Iwai603c4012008-07-30 15:01:44 +02006490 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +01006491 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +01006492
Takashi Iwaid88897e2008-10-31 15:01:37 +01006493 add_verb(spec, alc260_volume_init_verbs);
Kailang Yangdf694da2005-12-05 19:42:22 +01006494
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006495 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02006496 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006497
Kailang Yang6227cdc2010-02-25 08:36:52 +01006498 alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02006499
Kailang Yangdf694da2005-12-05 19:42:22 +01006500 return 1;
6501}
6502
Takashi Iwaiae6b8132006-03-03 16:47:17 +01006503/* additional initialization for auto-configuration model */
6504static void alc260_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +01006505{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006506 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01006507 alc260_auto_init_multi_out(codec);
6508 alc260_auto_init_analog_input(codec);
Takashi Iwai7f311a42010-04-09 17:32:23 +02006509 alc260_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006510 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +02006511 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +01006512}
6513
Takashi Iwaicb53c622007-08-10 17:21:45 +02006514#ifdef CONFIG_SND_HDA_POWER_SAVE
6515static struct hda_amp_list alc260_loopbacks[] = {
6516 { 0x07, HDA_INPUT, 0 },
6517 { 0x07, HDA_INPUT, 1 },
6518 { 0x07, HDA_INPUT, 2 },
6519 { 0x07, HDA_INPUT, 3 },
6520 { 0x07, HDA_INPUT, 4 },
6521 { } /* end */
6522};
6523#endif
6524
Kailang Yangdf694da2005-12-05 19:42:22 +01006525/*
6526 * ALC260 configurations
6527 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006528static const char *alc260_models[ALC260_MODEL_LAST] = {
6529 [ALC260_BASIC] = "basic",
6530 [ALC260_HP] = "hp",
6531 [ALC260_HP_3013] = "hp-3013",
Takashi Iwai2922c9a2008-08-27 18:12:42 +02006532 [ALC260_HP_DC7600] = "hp-dc7600",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006533 [ALC260_FUJITSU_S702X] = "fujitsu",
6534 [ALC260_ACER] = "acer",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006535 [ALC260_WILL] = "will",
6536 [ALC260_REPLACER_672V] = "replacer",
Michael Schwingencc959482009-02-22 18:58:45 +01006537 [ALC260_FAVORIT100] = "favorit100",
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006538#ifdef CONFIG_SND_DEBUG
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006539 [ALC260_TEST] = "test",
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006540#endif
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006541 [ALC260_AUTO] = "auto",
6542};
6543
6544static struct snd_pci_quirk alc260_cfg_tbl[] = {
Jonathan Woithebd869482006-11-28 11:35:52 +01006545 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
Daniel T Chen950200e2009-12-13 14:11:02 -05006546 SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006547 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
Michael Schwingencc959482009-02-22 18:58:45 +01006548 SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
Takashi Iwai9720b712007-03-13 21:46:23 +01006549 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
Takashi Iwai4ac55982009-11-10 16:08:45 +01006550 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006551 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
Jaroslav Kysela34ec8a02008-07-10 14:49:19 +02006552 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
Kailang Yang3f878302008-08-26 13:02:23 +02006553 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006554 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
6555 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
6556 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
6557 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
6558 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
6559 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
6560 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
6561 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
6562 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006563 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01006564 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
Takashi Iwai16ded522005-06-10 19:58:24 +02006565 {}
6566};
6567
Kailang Yangdf694da2005-12-05 19:42:22 +01006568static struct alc_config_preset alc260_presets[] = {
6569 [ALC260_BASIC] = {
6570 .mixers = { alc260_base_output_mixer,
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01006571 alc260_input_mixer },
Kailang Yangdf694da2005-12-05 19:42:22 +01006572 .init_verbs = { alc260_init_verbs },
6573 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6574 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006575 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
Takashi Iwai9c4cc0b2010-03-15 09:07:52 +01006576 .adc_nids = alc260_dual_adc_nids,
Kailang Yangdf694da2005-12-05 19:42:22 +01006577 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6578 .channel_mode = alc260_modes,
6579 .input_mux = &alc260_capture_source,
6580 },
6581 [ALC260_HP] = {
Takashi Iwaibec15c32008-01-28 18:16:30 +01006582 .mixers = { alc260_hp_output_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006583 alc260_input_mixer },
Takashi Iwaibec15c32008-01-28 18:16:30 +01006584 .init_verbs = { alc260_init_verbs,
6585 alc260_hp_unsol_verbs },
Kailang Yangdf694da2005-12-05 19:42:22 +01006586 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6587 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006588 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6589 .adc_nids = alc260_adc_nids_alt,
Kailang Yangdf694da2005-12-05 19:42:22 +01006590 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6591 .channel_mode = alc260_modes,
6592 .input_mux = &alc260_capture_source,
Takashi Iwaibec15c32008-01-28 18:16:30 +01006593 .unsol_event = alc260_hp_unsol_event,
6594 .init_hook = alc260_hp_automute,
Kailang Yangdf694da2005-12-05 19:42:22 +01006595 },
Kailang Yang3f878302008-08-26 13:02:23 +02006596 [ALC260_HP_DC7600] = {
6597 .mixers = { alc260_hp_dc7600_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006598 alc260_input_mixer },
Kailang Yang3f878302008-08-26 13:02:23 +02006599 .init_verbs = { alc260_init_verbs,
6600 alc260_hp_dc7600_verbs },
6601 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6602 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006603 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6604 .adc_nids = alc260_adc_nids_alt,
Kailang Yang3f878302008-08-26 13:02:23 +02006605 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6606 .channel_mode = alc260_modes,
6607 .input_mux = &alc260_capture_source,
6608 .unsol_event = alc260_hp_3012_unsol_event,
6609 .init_hook = alc260_hp_3012_automute,
6610 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006611 [ALC260_HP_3013] = {
6612 .mixers = { alc260_hp_3013_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006613 alc260_input_mixer },
Takashi Iwaibec15c32008-01-28 18:16:30 +01006614 .init_verbs = { alc260_hp_3013_init_verbs,
6615 alc260_hp_3013_unsol_verbs },
Kailang Yangdf694da2005-12-05 19:42:22 +01006616 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6617 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006618 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6619 .adc_nids = alc260_adc_nids_alt,
Kailang Yangdf694da2005-12-05 19:42:22 +01006620 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6621 .channel_mode = alc260_modes,
6622 .input_mux = &alc260_capture_source,
Takashi Iwaibec15c32008-01-28 18:16:30 +01006623 .unsol_event = alc260_hp_3013_unsol_event,
6624 .init_hook = alc260_hp_3013_automute,
Kailang Yangdf694da2005-12-05 19:42:22 +01006625 },
6626 [ALC260_FUJITSU_S702X] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006627 .mixers = { alc260_fujitsu_mixer },
Kailang Yangdf694da2005-12-05 19:42:22 +01006628 .init_verbs = { alc260_fujitsu_init_verbs },
6629 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6630 .dac_nids = alc260_dac_nids,
Jonathan Woithed57fdac2006-02-28 11:38:35 +01006631 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6632 .adc_nids = alc260_dual_adc_nids,
Kailang Yangdf694da2005-12-05 19:42:22 +01006633 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6634 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006635 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
6636 .input_mux = alc260_fujitsu_capture_sources,
Kailang Yangdf694da2005-12-05 19:42:22 +01006637 },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006638 [ALC260_ACER] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006639 .mixers = { alc260_acer_mixer },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006640 .init_verbs = { alc260_acer_init_verbs },
6641 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6642 .dac_nids = alc260_dac_nids,
6643 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6644 .adc_nids = alc260_dual_adc_nids,
6645 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6646 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006647 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
6648 .input_mux = alc260_acer_capture_sources,
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006649 },
Michael Schwingencc959482009-02-22 18:58:45 +01006650 [ALC260_FAVORIT100] = {
6651 .mixers = { alc260_favorit100_mixer },
6652 .init_verbs = { alc260_favorit100_init_verbs },
6653 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6654 .dac_nids = alc260_dac_nids,
6655 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6656 .adc_nids = alc260_dual_adc_nids,
6657 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6658 .channel_mode = alc260_modes,
6659 .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
6660 .input_mux = alc260_favorit100_capture_sources,
6661 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006662 [ALC260_WILL] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006663 .mixers = { alc260_will_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006664 .init_verbs = { alc260_init_verbs, alc260_will_verbs },
6665 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6666 .dac_nids = alc260_dac_nids,
6667 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
6668 .adc_nids = alc260_adc_nids,
6669 .dig_out_nid = ALC260_DIGOUT_NID,
6670 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6671 .channel_mode = alc260_modes,
6672 .input_mux = &alc260_capture_source,
6673 },
6674 [ALC260_REPLACER_672V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006675 .mixers = { alc260_replacer_672v_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006676 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
6677 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6678 .dac_nids = alc260_dac_nids,
6679 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
6680 .adc_nids = alc260_adc_nids,
6681 .dig_out_nid = ALC260_DIGOUT_NID,
6682 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6683 .channel_mode = alc260_modes,
6684 .input_mux = &alc260_capture_source,
6685 .unsol_event = alc260_replacer_672v_unsol_event,
6686 .init_hook = alc260_replacer_672v_automute,
6687 },
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006688#ifdef CONFIG_SND_DEBUG
6689 [ALC260_TEST] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006690 .mixers = { alc260_test_mixer },
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006691 .init_verbs = { alc260_test_init_verbs },
6692 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
6693 .dac_nids = alc260_test_dac_nids,
6694 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
6695 .adc_nids = alc260_test_adc_nids,
6696 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6697 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006698 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
6699 .input_mux = alc260_test_capture_sources,
Jonathan Woithe7cf51e482006-02-09 12:01:26 +01006700 },
6701#endif
Kailang Yangdf694da2005-12-05 19:42:22 +01006702};
6703
Linus Torvalds1da177e2005-04-16 15:20:36 -07006704static int patch_alc260(struct hda_codec *codec)
6705{
6706 struct alc_spec *spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01006707 int err, board_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006708
Takashi Iwaie560d8d2005-09-09 14:21:46 +02006709 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006710 if (spec == NULL)
6711 return -ENOMEM;
6712
6713 codec->spec = spec;
6714
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006715 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
6716 alc260_models,
6717 alc260_cfg_tbl);
6718 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02006719 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
Takashi Iwai6c627f32009-05-18 12:33:36 +02006720 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +01006721 board_config = ALC260_AUTO;
Takashi Iwai16ded522005-06-10 19:58:24 +02006722 }
6723
Kailang Yangdf694da2005-12-05 19:42:22 +01006724 if (board_config == ALC260_AUTO) {
6725 /* automatic parse from the BIOS config */
6726 err = alc260_parse_auto_config(codec);
6727 if (err < 0) {
6728 alc_free(codec);
6729 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006730 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02006731 printk(KERN_INFO
6732 "hda_codec: Cannot set up configuration "
6733 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +01006734 board_config = ALC260_BASIC;
6735 }
Takashi Iwai16ded522005-06-10 19:58:24 +02006736 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006737
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09006738 err = snd_hda_attach_beep_device(codec, 0x1);
6739 if (err < 0) {
6740 alc_free(codec);
6741 return err;
6742 }
6743
Kailang Yangdf694da2005-12-05 19:42:22 +01006744 if (board_config != ALC260_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02006745 setup_preset(codec, &alc260_presets[board_config]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006746
Linus Torvalds1da177e2005-04-16 15:20:36 -07006747 spec->stream_analog_playback = &alc260_pcm_analog_playback;
6748 spec->stream_analog_capture = &alc260_pcm_analog_capture;
6749
Takashi Iwaia3bcba32005-12-06 19:05:29 +01006750 spec->stream_digital_playback = &alc260_pcm_digital_playback;
6751 spec->stream_digital_capture = &alc260_pcm_digital_capture;
6752
Takashi Iwai4ef0ef12008-11-03 17:47:49 +01006753 if (!spec->adc_nids && spec->input_mux) {
6754 /* check whether NID 0x04 is valid */
6755 unsigned int wcap = get_wcaps(codec, 0x04);
Takashi Iwaia22d5432009-07-27 12:54:26 +02006756 wcap = get_wcaps_type(wcap);
Takashi Iwai4ef0ef12008-11-03 17:47:49 +01006757 /* get type */
6758 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
6759 spec->adc_nids = alc260_adc_nids_alt;
6760 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
6761 } else {
6762 spec->adc_nids = alc260_adc_nids;
6763 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
6764 }
6765 }
Takashi Iwaib59bdf32009-08-11 09:47:30 +02006766 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01006767 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006768
Takashi Iwai2134ea42008-01-10 16:53:55 +01006769 spec->vmaster_nid = 0x08;
6770
Linus Torvalds1da177e2005-04-16 15:20:36 -07006771 codec->patch_ops = alc_patch_ops;
Kailang Yangdf694da2005-12-05 19:42:22 +01006772 if (board_config == ALC260_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01006773 spec->init_hook = alc260_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +02006774#ifdef CONFIG_SND_HDA_POWER_SAVE
6775 if (!spec->loopback.amplist)
6776 spec->loopback.amplist = alc260_loopbacks;
6777#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006778
6779 return 0;
6780}
6781
Takashi Iwaie9edcee2005-06-13 14:16:38 +02006782
Linus Torvalds1da177e2005-04-16 15:20:36 -07006783/*
Takashi Iwai4953550a2009-06-30 15:28:30 +02006784 * ALC882/883/885/888/889 support
Linus Torvalds1da177e2005-04-16 15:20:36 -07006785 *
6786 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
6787 * configuration. Each pin widget can choose any input DACs and a mixer.
6788 * Each ADC is connected from a mixer of all inputs. This makes possible
6789 * 6-channel independent captures.
6790 *
6791 * In addition, an independent DAC for the multi-playback (not used in this
6792 * driver yet).
6793 */
Kailang Yangdf694da2005-12-05 19:42:22 +01006794#define ALC882_DIGOUT_NID 0x06
6795#define ALC882_DIGIN_NID 0x0a
Takashi Iwai4953550a2009-06-30 15:28:30 +02006796#define ALC883_DIGOUT_NID ALC882_DIGOUT_NID
6797#define ALC883_DIGIN_NID ALC882_DIGIN_NID
6798#define ALC1200_DIGOUT_NID 0x10
6799
Linus Torvalds1da177e2005-04-16 15:20:36 -07006800
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01006801static struct hda_channel_mode alc882_ch_modes[1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006802 { 8, NULL }
6803};
6804
Takashi Iwai4953550a2009-06-30 15:28:30 +02006805/* DACs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006806static hda_nid_t alc882_dac_nids[4] = {
6807 /* front, rear, clfe, rear_surr */
6808 0x02, 0x03, 0x04, 0x05
6809};
Takashi Iwai4953550a2009-06-30 15:28:30 +02006810#define alc883_dac_nids alc882_dac_nids
Linus Torvalds1da177e2005-04-16 15:20:36 -07006811
Takashi Iwai4953550a2009-06-30 15:28:30 +02006812/* ADCs */
Kailang Yangdf694da2005-12-05 19:42:22 +01006813#define alc882_adc_nids alc880_adc_nids
6814#define alc882_adc_nids_alt alc880_adc_nids_alt
Takashi Iwai4953550a2009-06-30 15:28:30 +02006815#define alc883_adc_nids alc882_adc_nids_alt
6816static hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
6817static hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
6818#define alc889_adc_nids alc880_adc_nids
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819
Takashi Iwaie1406342008-02-11 18:32:32 +01006820static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
6821static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
Takashi Iwai4953550a2009-06-30 15:28:30 +02006822#define alc883_capsrc_nids alc882_capsrc_nids_alt
6823static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
6824#define alc889_capsrc_nids alc882_capsrc_nids
Takashi Iwaie1406342008-02-11 18:32:32 +01006825
Linus Torvalds1da177e2005-04-16 15:20:36 -07006826/* input MUX */
6827/* FIXME: should be a matrix-type input source selection */
6828
6829static struct hda_input_mux alc882_capture_source = {
6830 .num_items = 4,
6831 .items = {
6832 { "Mic", 0x0 },
6833 { "Front Mic", 0x1 },
6834 { "Line", 0x2 },
6835 { "CD", 0x4 },
6836 },
6837};
Kacper Szczesniak41d55452009-05-07 12:47:43 +02006838
Takashi Iwai4953550a2009-06-30 15:28:30 +02006839#define alc883_capture_source alc882_capture_source
6840
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02006841static struct hda_input_mux alc889_capture_source = {
6842 .num_items = 3,
6843 .items = {
6844 { "Front Mic", 0x0 },
6845 { "Mic", 0x3 },
6846 { "Line", 0x2 },
6847 },
6848};
6849
Kacper Szczesniak41d55452009-05-07 12:47:43 +02006850static struct hda_input_mux mb5_capture_source = {
6851 .num_items = 3,
6852 .items = {
6853 { "Mic", 0x1 },
6854 { "Line", 0x2 },
6855 { "CD", 0x4 },
6856 },
6857};
6858
Luke Yelaviche458b1f2010-02-12 16:28:29 +11006859static struct hda_input_mux macmini3_capture_source = {
6860 .num_items = 2,
6861 .items = {
6862 { "Line", 0x2 },
6863 { "CD", 0x4 },
6864 },
6865};
6866
Takashi Iwai4953550a2009-06-30 15:28:30 +02006867static struct hda_input_mux alc883_3stack_6ch_intel = {
6868 .num_items = 4,
6869 .items = {
6870 { "Mic", 0x1 },
6871 { "Front Mic", 0x0 },
6872 { "Line", 0x2 },
6873 { "CD", 0x4 },
6874 },
6875};
6876
6877static struct hda_input_mux alc883_lenovo_101e_capture_source = {
6878 .num_items = 2,
6879 .items = {
6880 { "Mic", 0x1 },
6881 { "Line", 0x2 },
6882 },
6883};
6884
6885static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
6886 .num_items = 4,
6887 .items = {
6888 { "Mic", 0x0 },
6889 { "iMic", 0x1 },
6890 { "Line", 0x2 },
6891 { "CD", 0x4 },
6892 },
6893};
6894
6895static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
6896 .num_items = 2,
6897 .items = {
6898 { "Mic", 0x0 },
6899 { "Int Mic", 0x1 },
6900 },
6901};
6902
6903static struct hda_input_mux alc883_lenovo_sky_capture_source = {
6904 .num_items = 3,
6905 .items = {
6906 { "Mic", 0x0 },
6907 { "Front Mic", 0x1 },
6908 { "Line", 0x4 },
6909 },
6910};
6911
6912static struct hda_input_mux alc883_asus_eee1601_capture_source = {
6913 .num_items = 2,
6914 .items = {
6915 { "Mic", 0x0 },
6916 { "Line", 0x2 },
6917 },
6918};
6919
6920static struct hda_input_mux alc889A_mb31_capture_source = {
6921 .num_items = 2,
6922 .items = {
6923 { "Mic", 0x0 },
6924 /* Front Mic (0x01) unused */
6925 { "Line", 0x2 },
6926 /* Line 2 (0x03) unused */
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02006927 /* CD (0x04) unused? */
Takashi Iwai4953550a2009-06-30 15:28:30 +02006928 },
6929};
6930
6931/*
6932 * 2ch mode
6933 */
6934static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
6935 { 2, NULL }
6936};
6937
Kailang Yangdf694da2005-12-05 19:42:22 +01006938/*
Kailang Yang272a5272007-05-14 11:00:38 +02006939 * 2ch mode
6940 */
6941static struct hda_verb alc882_3ST_ch2_init[] = {
6942 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6943 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6944 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
6945 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6946 { } /* end */
6947};
6948
6949/*
Takashi Iwai4953550a2009-06-30 15:28:30 +02006950 * 4ch mode
6951 */
6952static struct hda_verb alc882_3ST_ch4_init[] = {
6953 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6954 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6955 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6956 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6957 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6958 { } /* end */
6959};
6960
6961/*
Kailang Yang272a5272007-05-14 11:00:38 +02006962 * 6ch mode
6963 */
6964static struct hda_verb alc882_3ST_ch6_init[] = {
6965 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6966 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6967 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
6968 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6969 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6970 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6971 { } /* end */
6972};
6973
Takashi Iwai4953550a2009-06-30 15:28:30 +02006974static struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
Kailang Yang272a5272007-05-14 11:00:38 +02006975 { 2, alc882_3ST_ch2_init },
Takashi Iwai4953550a2009-06-30 15:28:30 +02006976 { 4, alc882_3ST_ch4_init },
Kailang Yang272a5272007-05-14 11:00:38 +02006977 { 6, alc882_3ST_ch6_init },
6978};
6979
Takashi Iwai4953550a2009-06-30 15:28:30 +02006980#define alc883_3ST_6ch_modes alc882_3ST_6ch_modes
6981
Kailang Yang272a5272007-05-14 11:00:38 +02006982/*
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04306983 * 2ch mode
6984 */
6985static struct hda_verb alc883_3ST_ch2_clevo_init[] = {
6986 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
6987 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6988 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6989 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
6990 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6991 { } /* end */
6992};
6993
6994/*
6995 * 4ch mode
6996 */
6997static struct hda_verb alc883_3ST_ch4_clevo_init[] = {
6998 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6999 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7000 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7001 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7002 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7003 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7004 { } /* end */
7005};
7006
7007/*
7008 * 6ch mode
7009 */
7010static struct hda_verb alc883_3ST_ch6_clevo_init[] = {
7011 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7012 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7013 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7014 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7015 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7016 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7017 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7018 { } /* end */
7019};
7020
7021static struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
7022 { 2, alc883_3ST_ch2_clevo_init },
7023 { 4, alc883_3ST_ch4_clevo_init },
7024 { 6, alc883_3ST_ch6_clevo_init },
7025};
7026
7027
7028/*
Kailang Yangdf694da2005-12-05 19:42:22 +01007029 * 6ch mode
7030 */
7031static struct hda_verb alc882_sixstack_ch6_init[] = {
7032 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7033 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7034 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7035 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7036 { } /* end */
7037};
7038
7039/*
7040 * 8ch mode
7041 */
7042static struct hda_verb alc882_sixstack_ch8_init[] = {
7043 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7044 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7045 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7046 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7047 { } /* end */
7048};
7049
7050static struct hda_channel_mode alc882_sixstack_modes[2] = {
7051 { 6, alc882_sixstack_ch6_init },
7052 { 8, alc882_sixstack_ch8_init },
7053};
7054
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08007055
7056/* Macbook Air 2,1 */
7057
7058static struct hda_channel_mode alc885_mba21_ch_modes[1] = {
7059 { 2, NULL },
7060};
7061
Takashi Iwai87350ad2007-08-16 18:19:38 +02007062/*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04007063 * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
Takashi Iwai87350ad2007-08-16 18:19:38 +02007064 */
7065
7066/*
7067 * 2ch mode
7068 */
7069static struct hda_verb alc885_mbp_ch2_init[] = {
7070 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7071 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7072 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7073 { } /* end */
7074};
7075
7076/*
Takashi Iwaia3f730af2009-08-31 08:15:26 +02007077 * 4ch mode
Takashi Iwai87350ad2007-08-16 18:19:38 +02007078 */
Takashi Iwaia3f730af2009-08-31 08:15:26 +02007079static struct hda_verb alc885_mbp_ch4_init[] = {
Takashi Iwai87350ad2007-08-16 18:19:38 +02007080 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7081 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7082 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7083 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7084 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7085 { } /* end */
7086};
7087
Takashi Iwaia3f730af2009-08-31 08:15:26 +02007088static struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
Takashi Iwai87350ad2007-08-16 18:19:38 +02007089 { 2, alc885_mbp_ch2_init },
Takashi Iwaia3f730af2009-08-31 08:15:26 +02007090 { 4, alc885_mbp_ch4_init },
Takashi Iwai87350ad2007-08-16 18:19:38 +02007091};
7092
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007093/*
7094 * 2ch
7095 * Speakers/Woofer/HP = Front
7096 * LineIn = Input
7097 */
7098static struct hda_verb alc885_mb5_ch2_init[] = {
7099 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7100 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7101 { } /* end */
7102};
7103
7104/*
7105 * 6ch mode
7106 * Speakers/HP = Front
7107 * Woofer = LFE
7108 * LineIn = Surround
7109 */
7110static struct hda_verb alc885_mb5_ch6_init[] = {
7111 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7112 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7113 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
7114 { } /* end */
7115};
7116
7117static struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
7118 { 2, alc885_mb5_ch2_init },
7119 { 6, alc885_mb5_ch6_init },
7120};
Takashi Iwai87350ad2007-08-16 18:19:38 +02007121
Takashi Iwaid01aecd2010-02-23 08:07:15 +01007122#define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes
Takashi Iwai4953550a2009-06-30 15:28:30 +02007123
7124/*
7125 * 2ch mode
7126 */
7127static struct hda_verb alc883_4ST_ch2_init[] = {
7128 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7129 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7130 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7131 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7132 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7133 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7134 { } /* end */
7135};
7136
7137/*
7138 * 4ch mode
7139 */
7140static struct hda_verb alc883_4ST_ch4_init[] = {
7141 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7142 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7143 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7144 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7145 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7146 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7147 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7148 { } /* end */
7149};
7150
7151/*
7152 * 6ch mode
7153 */
7154static struct hda_verb alc883_4ST_ch6_init[] = {
7155 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7156 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7157 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7158 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7159 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7160 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7161 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7162 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7163 { } /* end */
7164};
7165
7166/*
7167 * 8ch mode
7168 */
7169static struct hda_verb alc883_4ST_ch8_init[] = {
7170 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7171 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7172 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7173 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7174 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7175 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7176 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7177 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7178 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7179 { } /* end */
7180};
7181
7182static struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
7183 { 2, alc883_4ST_ch2_init },
7184 { 4, alc883_4ST_ch4_init },
7185 { 6, alc883_4ST_ch6_init },
7186 { 8, alc883_4ST_ch8_init },
7187};
7188
7189
7190/*
7191 * 2ch mode
7192 */
7193static struct hda_verb alc883_3ST_ch2_intel_init[] = {
7194 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7195 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7196 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7197 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7198 { } /* end */
7199};
7200
7201/*
7202 * 4ch mode
7203 */
7204static struct hda_verb alc883_3ST_ch4_intel_init[] = {
7205 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7206 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7207 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7208 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7209 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7210 { } /* end */
7211};
7212
7213/*
7214 * 6ch mode
7215 */
7216static struct hda_verb alc883_3ST_ch6_intel_init[] = {
7217 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7218 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7219 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
7220 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7221 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7222 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7223 { } /* end */
7224};
7225
7226static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
7227 { 2, alc883_3ST_ch2_intel_init },
7228 { 4, alc883_3ST_ch4_intel_init },
7229 { 6, alc883_3ST_ch6_intel_init },
7230};
7231
7232/*
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007233 * 2ch mode
7234 */
7235static struct hda_verb alc889_ch2_intel_init[] = {
7236 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7237 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
7238 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
7239 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
7240 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7241 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7242 { } /* end */
7243};
7244
7245/*
Takashi Iwai4953550a2009-06-30 15:28:30 +02007246 * 6ch mode
7247 */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007248static struct hda_verb alc889_ch6_intel_init[] = {
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007249 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7250 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
7251 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
7252 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7253 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007254 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7255 { } /* end */
7256};
7257
7258/*
7259 * 8ch mode
7260 */
7261static struct hda_verb alc889_ch8_intel_init[] = {
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007262 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7263 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
7264 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
7265 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7266 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007267 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7268 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007269 { } /* end */
7270};
7271
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007272static struct hda_channel_mode alc889_8ch_intel_modes[3] = {
7273 { 2, alc889_ch2_intel_init },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007274 { 6, alc889_ch6_intel_init },
7275 { 8, alc889_ch8_intel_init },
7276};
7277
7278/*
7279 * 6ch mode
7280 */
Takashi Iwai4953550a2009-06-30 15:28:30 +02007281static struct hda_verb alc883_sixstack_ch6_init[] = {
7282 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7283 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7284 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7285 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7286 { } /* end */
7287};
7288
7289/*
7290 * 8ch mode
7291 */
7292static struct hda_verb alc883_sixstack_ch8_init[] = {
7293 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7294 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7295 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7296 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7297 { } /* end */
7298};
7299
7300static struct hda_channel_mode alc883_sixstack_modes[2] = {
7301 { 6, alc883_sixstack_ch6_init },
7302 { 8, alc883_sixstack_ch8_init },
7303};
7304
7305
Linus Torvalds1da177e2005-04-16 15:20:36 -07007306/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
7307 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
7308 */
Takashi Iwaic8b6bf92005-11-17 14:57:47 +01007309static struct snd_kcontrol_new alc882_base_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02007310 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007311 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007312 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007313 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007314 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
7315 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007316 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
7317 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007318 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007319 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007320 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7321 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7322 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7323 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7324 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7325 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01007326 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007327 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7328 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01007329 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007330 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007331 { } /* end */
7332};
7333
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08007334/* Macbook Air 2,1 same control for HP and internal Speaker */
7335
7336static struct snd_kcontrol_new alc885_mba21_mixer[] = {
7337 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7338 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
7339 { }
7340};
7341
7342
Takashi Iwai87350ad2007-08-16 18:19:38 +02007343static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
Takashi Iwaia3f730af2009-08-31 08:15:26 +02007344 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7345 HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
7346 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7347 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
7348 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01007349 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7350 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwai87350ad2007-08-16 18:19:38 +02007351 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
7352 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01007353 HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
Takashi Iwai87350ad2007-08-16 18:19:38 +02007354 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
7355 { } /* end */
7356};
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007357
7358static struct snd_kcontrol_new alc885_mb5_mixer[] = {
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007359 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7360 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
7361 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
7362 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
7363 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7364 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
Alex Murraya76221d2010-01-13 23:15:03 +10307365 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
7366 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007367 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7368 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7369 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
7370 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
7371 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
7372 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0x00, HDA_INPUT),
7373 { } /* end */
7374};
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007375
Luke Yelaviche458b1f2010-02-12 16:28:29 +11007376static struct snd_kcontrol_new alc885_macmini3_mixer[] = {
7377 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7378 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
7379 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
7380 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
7381 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7382 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
7383 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
7384 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
7385 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
7386 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
7387 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
7388 { } /* end */
7389};
7390
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08007391static struct snd_kcontrol_new alc885_imac91_mixer[] = {
7392 HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7393 HDA_BIND_MUTE ("Line-Out Playback Switch", 0x0c, 0x02, HDA_INPUT),
7394 HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),
7395 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
7396 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7397 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7398 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
7399 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
7400 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
7401 { } /* end */
7402};
7403
7404
Kailang Yangbdd148a2007-05-08 15:19:08 +02007405static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
7406 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7407 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7408 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7409 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7410 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7411 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7412 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7413 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7414 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangbdd148a2007-05-08 15:19:08 +02007415 { } /* end */
7416};
7417
Kailang Yang272a5272007-05-14 11:00:38 +02007418static struct snd_kcontrol_new alc882_targa_mixer[] = {
7419 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7420 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7421 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7422 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7423 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7424 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7425 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7426 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7427 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai96fe7cc82007-09-07 10:57:44 +02007428 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007429 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7430 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai96fe7cc82007-09-07 10:57:44 +02007431 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007432 { } /* end */
7433};
7434
7435/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
7436 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
7437 */
7438static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
7439 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7440 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7441 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7442 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
7443 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7444 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7445 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7446 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7447 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
7448 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
7449 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7450 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai96fe7cc82007-09-07 10:57:44 +02007451 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007452 { } /* end */
7453};
7454
Takashi Iwai914759b2007-09-06 14:52:04 +02007455static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
7456 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7457 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7458 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7459 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7460 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7461 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7462 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7464 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7465 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai914759b2007-09-06 14:52:04 +02007466 { } /* end */
7467};
7468
Kailang Yangdf694da2005-12-05 19:42:22 +01007469static struct snd_kcontrol_new alc882_chmode_mixer[] = {
7470 {
7471 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7472 .name = "Channel Mode",
7473 .info = alc_ch_mode_info,
7474 .get = alc_ch_mode_get,
7475 .put = alc_ch_mode_put,
7476 },
7477 { } /* end */
7478};
7479
Takashi Iwai4953550a2009-06-30 15:28:30 +02007480static struct hda_verb alc882_base_init_verbs[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007481 /* Front mixer: unmute input/output amp left and right (volume = 0) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007482 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7483 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007484 /* Rear mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007485 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7486 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007487 /* CLFE mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007488 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7489 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007490 /* Side mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007491 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7492 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007493
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007494 /* Front Pin: output 0 (0x0c) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007495 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007496 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007497 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007498 /* Rear Pin: output 1 (0x0d) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007499 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007500 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007501 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007502 /* CLFE Pin: output 2 (0x0e) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007503 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007504 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007505 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007506 /* Side Pin: output 3 (0x0f) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007507 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007508 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007509 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007510 /* Mic (rear) pin: input vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02007511 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007512 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7513 /* Front Mic pin: input vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02007514 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007515 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7516 /* Line In pin: input */
Takashi Iwai05acb862005-06-10 19:50:25 +02007517 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007518 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7519 /* Line-2 In: Headphone output (output 0 - 0x0c) */
7520 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7521 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7522 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007523 /* CD pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02007524 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007525
7526 /* FIXME: use matrix-type input source selection */
7527 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007528 /* Input mixer2 */
Takashi Iwai05acb862005-06-10 19:50:25 +02007529 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007530 /* Input mixer3 */
Takashi Iwai05acb862005-06-10 19:50:25 +02007531 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai05acb862005-06-10 19:50:25 +02007532 /* ADC2: mute amp left and right */
7533 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02007534 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02007535 /* ADC3: mute amp left and right */
7536 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02007537 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007538
7539 { }
7540};
7541
Takashi Iwai4953550a2009-06-30 15:28:30 +02007542static struct hda_verb alc882_adc1_init_verbs[] = {
7543 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7544 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7545 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7546 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7547 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7548 /* ADC1: mute amp left and right */
7549 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7550 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7551 { }
7552};
7553
Takashi Iwai4b146cb2006-07-28 14:42:36 +02007554static struct hda_verb alc882_eapd_verbs[] = {
7555 /* change to EAPD mode */
7556 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01007557 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02007558 { }
Takashi Iwai4b146cb2006-07-28 14:42:36 +02007559};
7560
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007561static struct hda_verb alc889_eapd_verbs[] = {
7562 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
7563 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
7564 { }
7565};
7566
Wu Fengguang6732bd02009-07-30 09:19:14 +02007567static struct hda_verb alc_hp15_unsol_verbs[] = {
7568 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
7569 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7570 {}
7571};
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007572
7573static struct hda_verb alc885_init_verbs[] = {
7574 /* Front mixer: unmute input/output amp left and right (volume = 0) */
Kailang Yang88102f32010-02-04 14:12:58 +01007575 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7576 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007577 /* Rear mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007578 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7579 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007580 /* CLFE mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007581 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7582 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007583 /* Side mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007584 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7585 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007586
7587 /* Front HP Pin: output 0 (0x0c) */
Wu Fengguang6732bd02009-07-30 09:19:14 +02007588 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007589 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7590 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7591 /* Front Pin: output 0 (0x0c) */
7592 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7593 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7594 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7595 /* Rear Pin: output 1 (0x0d) */
7596 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7597 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7598 {0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
7599 /* CLFE Pin: output 2 (0x0e) */
7600 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7601 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7602 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
7603 /* Side Pin: output 3 (0x0f) */
7604 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7605 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7606 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
7607 /* Mic (rear) pin: input vref at 80% */
7608 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7609 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7610 /* Front Mic pin: input vref at 80% */
7611 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7612 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7613 /* Line In pin: input */
7614 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7615 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7616
7617 /* Mixer elements: 0x18, , 0x1a, 0x1b */
7618 /* Input mixer1 */
Kailang Yang88102f32010-02-04 14:12:58 +01007619 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007620 /* Input mixer2 */
7621 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007622 /* Input mixer3 */
Kailang Yang88102f32010-02-04 14:12:58 +01007623 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007624 /* ADC2: mute amp left and right */
7625 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7626 /* ADC3: mute amp left and right */
7627 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7628
7629 { }
7630};
7631
7632static struct hda_verb alc885_init_input_verbs[] = {
7633 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7634 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7635 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7636 { }
7637};
7638
7639
7640/* Unmute Selector 24h and set the default input to front mic */
7641static struct hda_verb alc889_init_input_verbs[] = {
7642 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
7643 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7644 { }
7645};
7646
7647
Takashi Iwai4953550a2009-06-30 15:28:30 +02007648#define alc883_init_verbs alc882_base_init_verbs
7649
Tobin Davis9102cd12006-12-15 10:02:12 +01007650/* Mac Pro test */
7651static struct snd_kcontrol_new alc882_macpro_mixer[] = {
7652 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7653 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7654 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
7655 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
7656 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01007657 /* FIXME: this looks suspicious...
Jaroslav Kyselad355c82a2009-11-03 15:47:25 +01007658 HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
7659 HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01007660 */
Tobin Davis9102cd12006-12-15 10:02:12 +01007661 { } /* end */
7662};
7663
7664static struct hda_verb alc882_macpro_init_verbs[] = {
7665 /* Front mixer: unmute input/output amp left and right (volume = 0) */
7666 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7667 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7668 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7669 /* Front Pin: output 0 (0x0c) */
7670 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7671 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7672 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7673 /* Front Mic pin: input vref at 80% */
7674 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7675 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7676 /* Speaker: output */
7677 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7678 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7679 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
7680 /* Headphone output (output 0 - 0x0c) */
7681 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7682 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7683 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7684
7685 /* FIXME: use matrix-type input source selection */
7686 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7687 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7688 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7689 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7690 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7691 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7692 /* Input mixer2 */
7693 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7694 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7695 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7696 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7697 /* Input mixer3 */
7698 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7699 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7700 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7701 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7702 /* ADC1: mute amp left and right */
7703 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7704 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7705 /* ADC2: mute amp left and right */
7706 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7707 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7708 /* ADC3: mute amp left and right */
7709 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7710 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7711
7712 { }
7713};
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02007714
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007715/* Macbook 5,1 */
7716static struct hda_verb alc885_mb5_init_verbs[] = {
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007717 /* DACs */
7718 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7719 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7720 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7721 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007722 /* Front mixer */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007723 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7724 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7725 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007726 /* Surround mixer */
7727 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7728 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7729 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7730 /* LFE mixer */
7731 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7732 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7733 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7734 /* HP mixer */
7735 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7736 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7737 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7738 /* Front Pin (0x0c) */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007739 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
7740 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007741 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7742 /* LFE Pin (0x0e) */
7743 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
7744 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7745 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
7746 /* HP Pin (0x0f) */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007747 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7748 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007749 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
Alex Murraya76221d2010-01-13 23:15:03 +10307750 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007751 /* Front Mic pin: input vref at 80% */
7752 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7753 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7754 /* Line In pin */
7755 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7756 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7757
7758 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7759 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7760 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7761 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7762 { }
7763};
7764
Luke Yelaviche458b1f2010-02-12 16:28:29 +11007765/* Macmini 3,1 */
7766static struct hda_verb alc885_macmini3_init_verbs[] = {
7767 /* DACs */
7768 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7769 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7770 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7771 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7772 /* Front mixer */
7773 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7774 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7775 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7776 /* Surround mixer */
7777 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7778 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7779 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7780 /* LFE mixer */
7781 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7782 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7783 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7784 /* HP mixer */
7785 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7786 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7787 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7788 /* Front Pin (0x0c) */
7789 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
7790 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7791 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7792 /* LFE Pin (0x0e) */
7793 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
7794 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7795 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
7796 /* HP Pin (0x0f) */
7797 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7798 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7799 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
7800 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7801 /* Line In pin */
7802 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7803 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7804
7805 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7806 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7807 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7808 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7809 { }
7810};
7811
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08007812
7813static struct hda_verb alc885_mba21_init_verbs[] = {
7814 /*Internal and HP Speaker Mixer*/
7815 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7816 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7817 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7818 /*Internal Speaker Pin (0x0c)*/
7819 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
7820 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7821 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7822 /* HP Pin: output 0 (0x0e) */
7823 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
7824 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7825 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7826 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
7827 /* Line in (is hp when jack connected)*/
7828 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
7829 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7830
7831 { }
7832 };
7833
7834
Takashi Iwai87350ad2007-08-16 18:19:38 +02007835/* Macbook Pro rev3 */
7836static struct hda_verb alc885_mbp3_init_verbs[] = {
7837 /* Front mixer: unmute input/output amp left and right (volume = 0) */
7838 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7839 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7840 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7841 /* Rear mixer */
7842 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7843 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7844 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwaia3f730af2009-08-31 08:15:26 +02007845 /* HP mixer */
7846 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7847 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7848 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai87350ad2007-08-16 18:19:38 +02007849 /* Front Pin: output 0 (0x0c) */
7850 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7851 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7852 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaia3f730af2009-08-31 08:15:26 +02007853 /* HP Pin: output 0 (0x0e) */
Takashi Iwai87350ad2007-08-16 18:19:38 +02007854 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
Takashi Iwaia3f730af2009-08-31 08:15:26 +02007855 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7856 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai87350ad2007-08-16 18:19:38 +02007857 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7858 /* Mic (rear) pin: input vref at 80% */
7859 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7860 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7861 /* Front Mic pin: input vref at 80% */
7862 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7863 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7864 /* Line In pin: use output 1 when in LineOut mode */
7865 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7866 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7867 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
7868
7869 /* FIXME: use matrix-type input source selection */
7870 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7871 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7872 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7873 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7874 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7875 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7876 /* Input mixer2 */
7877 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7878 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7879 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7880 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7881 /* Input mixer3 */
7882 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7883 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7884 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7885 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7886 /* ADC1: mute amp left and right */
7887 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7888 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7889 /* ADC2: mute amp left and right */
7890 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7891 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7892 /* ADC3: mute amp left and right */
7893 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7894 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7895
7896 { }
7897};
7898
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08007899/* iMac 9,1 */
7900static struct hda_verb alc885_imac91_init_verbs[] = {
7901 /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
7902 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7903 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7904 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7905 /* Rear mixer */
7906 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7907 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7908 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7909 /* HP Pin: output 0 (0x0c) */
7910 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7911 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7912 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7913 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7914 /* Internal Speakers: output 0 (0x0d) */
7915 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7916 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7917 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7918 /* Mic (rear) pin: input vref at 80% */
7919 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7920 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7921 /* Front Mic pin: input vref at 80% */
7922 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7923 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7924 /* Line In pin: use output 1 when in LineOut mode */
7925 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7926 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7927 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
7928
7929 /* FIXME: use matrix-type input source selection */
7930 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7931 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7932 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7933 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7934 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7935 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7936 /* Input mixer2 */
7937 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7938 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7939 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7940 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7941 /* Input mixer3 */
7942 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7943 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7944 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7945 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7946 /* ADC1: mute amp left and right */
7947 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7948 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7949 /* ADC2: mute amp left and right */
7950 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7951 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7952 /* ADC3: mute amp left and right */
7953 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7954 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7955
7956 { }
7957};
7958
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007959/* iMac 24 mixer. */
7960static struct snd_kcontrol_new alc885_imac24_mixer[] = {
7961 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7962 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
7963 { } /* end */
7964};
7965
7966/* iMac 24 init verbs. */
7967static struct hda_verb alc885_imac24_init_verbs[] = {
7968 /* Internal speakers: output 0 (0x0c) */
7969 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7970 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7971 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7972 /* Internal speakers: output 0 (0x0c) */
7973 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7974 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7975 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
7976 /* Headphone: output 0 (0x0c) */
7977 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7978 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7979 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7980 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7981 /* Front Mic: input vref at 80% */
7982 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7983 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7984 { }
7985};
7986
7987/* Toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02007988static void alc885_imac24_setup(struct hda_codec *codec)
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007989{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007990 struct alc_spec *spec = codec->spec;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007991
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007992 spec->autocfg.hp_pins[0] = 0x14;
7993 spec->autocfg.speaker_pins[0] = 0x18;
7994 spec->autocfg.speaker_pins[1] = 0x1a;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007995}
7996
Takashi Iwai9d54f082010-02-22 08:34:40 +01007997#define alc885_mb5_setup alc885_imac24_setup
7998#define alc885_macmini3_setup alc885_imac24_setup
7999
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08008000/* Macbook Air 2,1 */
8001static void alc885_mba21_setup(struct hda_codec *codec)
8002{
8003 struct alc_spec *spec = codec->spec;
8004
8005 spec->autocfg.hp_pins[0] = 0x14;
8006 spec->autocfg.speaker_pins[0] = 0x18;
8007}
8008
8009
8010
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008011static void alc885_mbp3_setup(struct hda_codec *codec)
Nicola Fagnanic54728d2007-07-19 23:28:52 +02008012{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008013 struct alc_spec *spec = codec->spec;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02008014
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008015 spec->autocfg.hp_pins[0] = 0x15;
8016 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai87350ad2007-08-16 18:19:38 +02008017}
8018
Takashi Iwai9d54f082010-02-22 08:34:40 +01008019static void alc885_imac91_setup(struct hda_codec *codec)
Alex Murraya76221d2010-01-13 23:15:03 +10308020{
Takashi Iwai9d54f082010-02-22 08:34:40 +01008021 struct alc_spec *spec = codec->spec;
Alex Murraya76221d2010-01-13 23:15:03 +10308022
Takashi Iwai9d54f082010-02-22 08:34:40 +01008023 spec->autocfg.hp_pins[0] = 0x14;
8024 spec->autocfg.speaker_pins[0] = 0x15;
8025 spec->autocfg.speaker_pins[1] = 0x1a;
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008026}
Takashi Iwai87350ad2007-08-16 18:19:38 +02008027
Kailang Yang272a5272007-05-14 11:00:38 +02008028static struct hda_verb alc882_targa_verbs[] = {
8029 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8030 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8031
8032 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8033 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02008034
Kailang Yang272a5272007-05-14 11:00:38 +02008035 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8036 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8037 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8038
8039 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yang272a5272007-05-14 11:00:38 +02008040 { } /* end */
8041};
8042
8043/* toggle speaker-output according to the hp-jack state */
8044static void alc882_targa_automute(struct hda_codec *codec)
8045{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008046 struct alc_spec *spec = codec->spec;
8047 alc_automute_amp(codec);
Takashi Iwai82beb8f2007-08-10 17:09:26 +02008048 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008049 spec->jack_present ? 1 : 3);
8050}
8051
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008052static void alc882_targa_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008053{
8054 struct alc_spec *spec = codec->spec;
8055
8056 spec->autocfg.hp_pins[0] = 0x14;
8057 spec->autocfg.speaker_pins[0] = 0x1b;
Kailang Yang272a5272007-05-14 11:00:38 +02008058}
8059
8060static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
8061{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008062 if ((res >> 26) == ALC880_HP_EVENT)
Kailang Yang272a5272007-05-14 11:00:38 +02008063 alc882_targa_automute(codec);
Kailang Yang272a5272007-05-14 11:00:38 +02008064}
8065
8066static struct hda_verb alc882_asus_a7j_verbs[] = {
8067 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8068 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8069
8070 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8071 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8072 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02008073
Kailang Yang272a5272007-05-14 11:00:38 +02008074 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8075 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8076 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8077
8078 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8079 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8080 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8081 { } /* end */
8082};
8083
Takashi Iwai914759b2007-09-06 14:52:04 +02008084static struct hda_verb alc882_asus_a7m_verbs[] = {
8085 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8086 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8087
8088 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8089 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8090 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02008091
Takashi Iwai914759b2007-09-06 14:52:04 +02008092 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8093 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8094 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8095
8096 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8097 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8098 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8099 { } /* end */
8100};
8101
Tobin Davis9102cd12006-12-15 10:02:12 +01008102static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
8103{
8104 unsigned int gpiostate, gpiomask, gpiodir;
8105
8106 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
8107 AC_VERB_GET_GPIO_DATA, 0);
8108
8109 if (!muted)
8110 gpiostate |= (1 << pin);
8111 else
8112 gpiostate &= ~(1 << pin);
8113
8114 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
8115 AC_VERB_GET_GPIO_MASK, 0);
8116 gpiomask |= (1 << pin);
8117
8118 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
8119 AC_VERB_GET_GPIO_DIRECTION, 0);
8120 gpiodir |= (1 << pin);
8121
8122
8123 snd_hda_codec_write(codec, codec->afg, 0,
8124 AC_VERB_SET_GPIO_MASK, gpiomask);
8125 snd_hda_codec_write(codec, codec->afg, 0,
8126 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
8127
8128 msleep(1);
8129
8130 snd_hda_codec_write(codec, codec->afg, 0,
8131 AC_VERB_SET_GPIO_DATA, gpiostate);
8132}
8133
Takashi Iwai7debbe52007-08-16 15:01:03 +02008134/* set up GPIO at initialization */
8135static void alc885_macpro_init_hook(struct hda_codec *codec)
8136{
8137 alc882_gpio_mute(codec, 0, 0);
8138 alc882_gpio_mute(codec, 1, 0);
8139}
8140
8141/* set up GPIO and update auto-muting at initialization */
8142static void alc885_imac24_init_hook(struct hda_codec *codec)
8143{
8144 alc885_macpro_init_hook(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008145 alc_automute_amp(codec);
Takashi Iwai7debbe52007-08-16 15:01:03 +02008146}
8147
Kailang Yangdf694da2005-12-05 19:42:22 +01008148/*
8149 * generic initialization of ADC, input mixers and output mixers
8150 */
Takashi Iwai4953550a2009-06-30 15:28:30 +02008151static struct hda_verb alc883_auto_init_verbs[] = {
Kailang Yangdf694da2005-12-05 19:42:22 +01008152 /*
8153 * Unmute ADC0-2 and set the default input to mic-in
8154 */
Kailang Yangdf694da2005-12-05 19:42:22 +01008155 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8156 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8157 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8158 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8159
Kailang Yangdf694da2005-12-05 19:42:22 +01008160 /*
8161 * Set up output mixers (0x0c - 0x0f)
8162 */
8163 /* set vol=0 to output mixers */
8164 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8165 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8166 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8167 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8168 /* set up input amps for analog loopback */
8169 /* Amp Indices: DAC = 0, mixer = 1 */
8170 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8171 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8172 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8173 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8174 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8175 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8176 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8177 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8178 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8179 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8180
8181 /* FIXME: use matrix-type input source selection */
8182 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
Kailang Yangdf694da2005-12-05 19:42:22 +01008183 /* Input mixer2 */
Kailang Yang88102f32010-02-04 14:12:58 +01008184 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangdf694da2005-12-05 19:42:22 +01008185 /* Input mixer3 */
Kailang Yang88102f32010-02-04 14:12:58 +01008186 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangdf694da2005-12-05 19:42:22 +01008187 { }
8188};
8189
Torben Schulzeb4c41d2009-05-18 15:02:35 +02008190/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
8191static struct hda_verb alc889A_mb31_ch2_init[] = {
8192 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
8193 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8194 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
8195 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
8196 { } /* end */
8197};
8198
8199/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
8200static struct hda_verb alc889A_mb31_ch4_init[] = {
8201 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
8202 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8203 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
8204 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
8205 { } /* end */
8206};
8207
8208/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
8209static struct hda_verb alc889A_mb31_ch5_init[] = {
8210 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */
8211 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8212 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
8213 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
8214 { } /* end */
8215};
8216
8217/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
8218static struct hda_verb alc889A_mb31_ch6_init[] = {
8219 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */
8220 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */
8221 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
8222 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
8223 { } /* end */
8224};
8225
8226static struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
8227 { 2, alc889A_mb31_ch2_init },
8228 { 4, alc889A_mb31_ch4_init },
8229 { 5, alc889A_mb31_ch5_init },
8230 { 6, alc889A_mb31_ch6_init },
8231};
8232
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01008233static struct hda_verb alc883_medion_eapd_verbs[] = {
8234 /* eanable EAPD on medion laptop */
8235 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
8236 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
8237 { }
8238};
8239
Takashi Iwai4953550a2009-06-30 15:28:30 +02008240#define alc883_base_mixer alc882_base_mixer
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008241
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008242static struct snd_kcontrol_new alc883_mitac_mixer[] = {
8243 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8244 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8245 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8246 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8247 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8248 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8249 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8250 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8251 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8252 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8253 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8254 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8255 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008256 { } /* end */
8257};
8258
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008259static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
Jiang zhe368c7a92008-03-04 11:20:33 +01008260 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8261 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
8262 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8263 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
8264 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8265 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8266 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8267 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8268 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8269 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Jiang zhe368c7a92008-03-04 11:20:33 +01008270 { } /* end */
8271};
8272
Jiang zhefb97dc62008-03-06 11:07:11 +01008273static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
8274 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8275 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
8276 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8277 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
8278 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8279 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8280 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8281 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8282 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8283 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Jiang zhefb97dc62008-03-06 11:07:11 +01008284 { } /* end */
8285};
8286
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008287static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
8288 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8289 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8290 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8291 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8292 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8293 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8294 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8295 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008296 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008297 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8298 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008299 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008300 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008301 { } /* end */
8302};
8303
8304static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
8305 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8306 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8307 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8308 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8309 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8310 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8311 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8312 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8313 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8314 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8315 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8316 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8317 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8318 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008319 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008320 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8321 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008322 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008323 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008324 { } /* end */
8325};
8326
Jiang zhe17bba1b2008-06-04 12:11:07 +02008327static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
8328 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8329 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8330 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8331 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8332 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
8333 HDA_OUTPUT),
8334 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8335 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8336 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8337 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8338 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8339 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8340 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8341 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8342 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8343 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
8344 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8345 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8346 HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
8347 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Jiang zhe17bba1b2008-06-04 12:11:07 +02008348 { } /* end */
8349};
8350
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02008351static struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
8352 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8353 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8354 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8355 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8356 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
8357 HDA_OUTPUT),
8358 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8359 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8360 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8361 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8362 HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
8363 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8364 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8365 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8366 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
8367 HDA_CODEC_VOLUME("Mic Boost", 0x1b, 0, HDA_INPUT),
8368 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
8369 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8370 HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
8371 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8372 { } /* end */
8373};
8374
Takashi Iwaid1d985f2006-11-23 19:27:12 +01008375static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
Tobin Davisc07584c2006-10-13 12:32:16 +02008376 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008377 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008378 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008379 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008380 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8381 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008382 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8383 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008384 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8385 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8386 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8387 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8388 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8389 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008390 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008391 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8392 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008393 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008394 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008395 { } /* end */
8396};
8397
Sasha Alexandrc2592492009-06-16 14:52:54 -04008398static struct snd_kcontrol_new alc883_targa_mixer[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02008399 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008400 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008401 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008402 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008403 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8404 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8405 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8406 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8407 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8408 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8409 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8410 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8411 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8412 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8413 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008414 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008415 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008416 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008417};
Kailang Yangccc656c2006-10-17 12:32:26 +02008418
Sasha Alexandrc2592492009-06-16 14:52:54 -04008419static struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02008420 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008421 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008422 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008423 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008424 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8425 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8426 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008427 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008428 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Jiang zhe4383fae2008-04-14 12:58:57 +02008429 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8430 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8431 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008432 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008433};
Kailang Yangccc656c2006-10-17 12:32:26 +02008434
Takashi Iwaib99dba32009-09-17 18:23:00 +02008435static struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
8436 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8437 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
8438 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8439 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8440 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8441 { } /* end */
8442};
8443
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008444static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
8445 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8446 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +01008447 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8448 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008449 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8450 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8451 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8452 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008453 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008454};
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008455
Kailang Yang272a5272007-05-14 11:00:38 +02008456static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
8457 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8458 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
8459 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8460 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8461 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8462 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8463 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8464 HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8465 HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02008466 { } /* end */
8467};
8468
8469static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
8470 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8471 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8472 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8473 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8474 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8475 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8476 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8477 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8478 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02008479 { } /* end */
Kailang Yangea1fb292008-08-26 12:58:38 +02008480};
Kailang Yang272a5272007-05-14 11:00:38 +02008481
Maurus Cuelenaere7ad7b212010-04-06 18:12:52 +02008482static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
8483 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8484 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8485 HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8486 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
8487 HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT),
8488 HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT),
8489 { } /* end */
8490};
8491
8492static struct hda_verb alc883_medion_wim2160_verbs[] = {
8493 /* Unmute front mixer */
8494 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8495 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8496
8497 /* Set speaker pin to front mixer */
8498 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8499
8500 /* Init headphone pin */
8501 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8502 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8503 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8504 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8505
8506 { } /* end */
8507};
8508
8509/* toggle speaker-output according to the hp-jack state */
8510static void alc883_medion_wim2160_setup(struct hda_codec *codec)
8511{
8512 struct alc_spec *spec = codec->spec;
8513
8514 spec->autocfg.hp_pins[0] = 0x1a;
8515 spec->autocfg.speaker_pins[0] = 0x15;
8516}
8517
Tobin Davis2880a862007-08-07 11:50:26 +02008518static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
Kailang Yangd1a991a2007-08-15 16:21:59 +02008519 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8520 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008521 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008522 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8523 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Kailang Yangd1a991a2007-08-15 16:21:59 +02008524 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8525 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8526 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008527 { } /* end */
Kailang Yangd1a991a2007-08-15 16:21:59 +02008528};
Tobin Davis2880a862007-08-07 11:50:26 +02008529
Tony Vroond2fd4b02009-06-21 00:40:10 +01008530static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
8531 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Tony Vroond2fd4b02009-06-21 00:40:10 +01008532 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Tony Vroon684a8842009-06-26 09:27:50 +01008533 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8534 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Tony Vroond2fd4b02009-06-21 00:40:10 +01008535 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8536 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8537 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8538 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8539 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8540 { } /* end */
8541};
8542
Kailang Yange2757d52008-08-26 13:17:46 +02008543static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
8544 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8545 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8546 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
8547 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
8548 HDA_CODEC_VOLUME_MONO("Center Playback Volume",
8549 0x0d, 1, 0x0, HDA_OUTPUT),
8550 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
8551 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
8552 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
8553 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8554 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Kailang Yange2757d52008-08-26 13:17:46 +02008555 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8556 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8557 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8558 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8559 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8560 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8561 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8562 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8563 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8564 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yange2757d52008-08-26 13:17:46 +02008565 { } /* end */
8566};
8567
Torben Schulzeb4c41d2009-05-18 15:02:35 +02008568static struct snd_kcontrol_new alc889A_mb31_mixer[] = {
8569 /* Output mixers */
8570 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8571 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
8572 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8573 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
8574 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
8575 HDA_OUTPUT),
8576 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
8577 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
8578 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
8579 /* Output switches */
8580 HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
8581 HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
8582 HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
8583 /* Boost mixers */
8584 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
8585 HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
8586 /* Input mixers */
8587 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
8588 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
8589 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8590 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8591 { } /* end */
8592};
8593
Guido Günther3e1647c2009-06-05 00:47:26 +02008594static struct snd_kcontrol_new alc883_vaiott_mixer[] = {
8595 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8596 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8597 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8598 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8599 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
8600 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8601 { } /* end */
8602};
8603
Kailang Yange2757d52008-08-26 13:17:46 +02008604static struct hda_bind_ctls alc883_bind_cap_vol = {
8605 .ops = &snd_hda_bind_vol,
8606 .values = {
8607 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
8608 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
8609 0
8610 },
8611};
8612
8613static struct hda_bind_ctls alc883_bind_cap_switch = {
8614 .ops = &snd_hda_bind_sw,
8615 .values = {
8616 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
8617 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
8618 0
8619 },
8620};
8621
8622static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
8623 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8624 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8625 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8626 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8627 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8628 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8629 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8630 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaif9e336f2008-10-31 16:37:07 +01008631 { } /* end */
8632};
8633
8634static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
Kailang Yange2757d52008-08-26 13:17:46 +02008635 HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
8636 HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
8637 {
8638 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8639 /* .name = "Capture Source", */
8640 .name = "Input Source",
8641 .count = 1,
Takashi Iwai54cbc9a2008-10-31 15:24:04 +01008642 .info = alc_mux_enum_info,
8643 .get = alc_mux_enum_get,
8644 .put = alc_mux_enum_put,
Kailang Yange2757d52008-08-26 13:17:46 +02008645 },
8646 { } /* end */
8647};
8648
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008649static struct snd_kcontrol_new alc883_chmode_mixer[] = {
8650 {
8651 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8652 .name = "Channel Mode",
8653 .info = alc_ch_mode_info,
8654 .get = alc_ch_mode_get,
8655 .put = alc_ch_mode_put,
8656 },
8657 { } /* end */
8658};
8659
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008660/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008661static void alc883_mitac_setup(struct hda_codec *codec)
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008662{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008663 struct alc_spec *spec = codec->spec;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008664
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008665 spec->autocfg.hp_pins[0] = 0x15;
8666 spec->autocfg.speaker_pins[0] = 0x14;
8667 spec->autocfg.speaker_pins[1] = 0x17;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008668}
8669
8670/* auto-toggle front mic */
8671/*
8672static void alc883_mitac_mic_automute(struct hda_codec *codec)
8673{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008674 unsigned char bits = snd_hda_jack_detect(codec, 0x18) ? HDA_AMP_MUTE : 0;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008675
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008676 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
8677}
8678*/
8679
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008680static struct hda_verb alc883_mitac_verbs[] = {
8681 /* HP */
8682 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8683 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8684 /* Subwoofer */
8685 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
8686 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8687
8688 /* enable unsolicited event */
8689 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8690 /* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, */
8691
8692 { } /* end */
8693};
8694
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04308695static struct hda_verb alc883_clevo_m540r_verbs[] = {
8696 /* HP */
8697 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8698 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8699 /* Int speaker */
8700 /*{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},*/
8701
8702 /* enable unsolicited event */
8703 /*
8704 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8705 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
8706 */
8707
8708 { } /* end */
8709};
8710
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008711static struct hda_verb alc883_clevo_m720_verbs[] = {
Jiang zhe368c7a92008-03-04 11:20:33 +01008712 /* HP */
8713 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8714 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8715 /* Int speaker */
8716 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
8717 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8718
8719 /* enable unsolicited event */
8720 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008721 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
Jiang zhe368c7a92008-03-04 11:20:33 +01008722
8723 { } /* end */
8724};
8725
Jiang zhefb97dc62008-03-06 11:07:11 +01008726static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
8727 /* HP */
8728 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8729 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8730 /* Subwoofer */
8731 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
8732 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8733
8734 /* enable unsolicited event */
8735 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8736
8737 { } /* end */
8738};
8739
Sasha Alexandrc2592492009-06-16 14:52:54 -04008740static struct hda_verb alc883_targa_verbs[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02008741 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8742 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8743
8744 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8745 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02008746
David Heidelberger64a8be72009-06-08 16:15:18 +02008747/* Connect Line-Out side jack (SPDIF) to Side */
8748 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8749 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8750 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
8751/* Connect Mic jack to CLFE */
8752 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8753 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8754 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
8755/* Connect Line-in jack to Surround */
8756 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8757 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8758 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
8759/* Connect HP out jack to Front */
8760 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8761 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8762 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangccc656c2006-10-17 12:32:26 +02008763
8764 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yangccc656c2006-10-17 12:32:26 +02008765
8766 { } /* end */
8767};
8768
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008769static struct hda_verb alc883_lenovo_101e_verbs[] = {
8770 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8771 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
8772 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
8773 { } /* end */
8774};
8775
Kailang Yang272a5272007-05-14 11:00:38 +02008776static struct hda_verb alc883_lenovo_nb0763_verbs[] = {
8777 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8778 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8779 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8780 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8781 { } /* end */
8782};
8783
8784static struct hda_verb alc888_lenovo_ms7195_verbs[] = {
8785 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8786 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8787 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8788 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},
8789 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8790 { } /* end */
8791};
8792
Kailang Yang189609a2007-08-20 11:31:23 +02008793static struct hda_verb alc883_haier_w66_verbs[] = {
8794 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8795 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8796
8797 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8798
8799 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
8800 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8801 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8802 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8803 { } /* end */
8804};
8805
Kailang Yange2757d52008-08-26 13:17:46 +02008806static struct hda_verb alc888_lenovo_sky_verbs[] = {
8807 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8808 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8809 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8810 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8811 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8812 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8813 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8814 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8815 { } /* end */
8816};
8817
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008818static struct hda_verb alc888_6st_dell_verbs[] = {
8819 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8820 { }
8821};
8822
Guido Günther3e1647c2009-06-05 00:47:26 +02008823static struct hda_verb alc883_vaiott_verbs[] = {
8824 /* HP */
8825 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8826 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8827
8828 /* enable unsolicited event */
8829 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8830
8831 { } /* end */
8832};
8833
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008834static void alc888_3st_hp_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008835{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008836 struct alc_spec *spec = codec->spec;
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008837
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008838 spec->autocfg.hp_pins[0] = 0x1b;
8839 spec->autocfg.speaker_pins[0] = 0x14;
8840 spec->autocfg.speaker_pins[1] = 0x16;
8841 spec->autocfg.speaker_pins[2] = 0x18;
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008842}
8843
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008844static struct hda_verb alc888_3st_hp_verbs[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008845 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
Herton Ronaldo Krzesinskif32a19e2008-03-18 09:27:08 +01008846 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
8847 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01008848 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008849 { } /* end */
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01008850};
8851
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008852/*
8853 * 2ch mode
8854 */
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008855static struct hda_verb alc888_3st_hp_2ch_init[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008856 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8857 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8858 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8859 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008860 { } /* end */
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008861};
8862
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008863/*
8864 * 4ch mode
8865 */
8866static struct hda_verb alc888_3st_hp_4ch_init[] = {
8867 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8868 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8869 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8870 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8871 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
8872 { } /* end */
8873};
8874
8875/*
8876 * 6ch mode
8877 */
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008878static struct hda_verb alc888_3st_hp_6ch_init[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008879 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8880 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008881 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008882 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8883 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008884 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
8885 { } /* end */
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008886};
8887
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008888static struct hda_channel_mode alc888_3st_hp_modes[3] = {
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008889 { 2, alc888_3st_hp_2ch_init },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008890 { 4, alc888_3st_hp_4ch_init },
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008891 { 6, alc888_3st_hp_6ch_init },
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008892};
8893
Kailang Yang272a5272007-05-14 11:00:38 +02008894/* toggle front-jack and RCA according to the hp-jack state */
8895static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
8896{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008897 unsigned int present = snd_hda_jack_detect(codec, 0x1b);
Kailang Yangea1fb292008-08-26 12:58:38 +02008898
Takashi Iwai47fd8302007-08-10 17:11:07 +02008899 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
8900 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
8901 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8902 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
Kailang Yang272a5272007-05-14 11:00:38 +02008903}
8904
8905/* toggle RCA according to the front-jack state */
8906static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
8907{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008908 unsigned int present = snd_hda_jack_detect(codec, 0x14);
Kailang Yangea1fb292008-08-26 12:58:38 +02008909
Takashi Iwai47fd8302007-08-10 17:11:07 +02008910 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8911 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
Kailang Yang272a5272007-05-14 11:00:38 +02008912}
Takashi Iwai47fd8302007-08-10 17:11:07 +02008913
Kailang Yang272a5272007-05-14 11:00:38 +02008914static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
8915 unsigned int res)
8916{
8917 if ((res >> 26) == ALC880_HP_EVENT)
8918 alc888_lenovo_ms7195_front_automute(codec);
8919 if ((res >> 26) == ALC880_FRONT_EVENT)
8920 alc888_lenovo_ms7195_rca_automute(codec);
8921}
8922
8923static struct hda_verb alc883_medion_md2_verbs[] = {
8924 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8925 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8926
8927 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8928
8929 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8930 { } /* end */
8931};
8932
8933/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008934static void alc883_medion_md2_setup(struct hda_codec *codec)
Kailang Yang272a5272007-05-14 11:00:38 +02008935{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008936 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02008937
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008938 spec->autocfg.hp_pins[0] = 0x14;
8939 spec->autocfg.speaker_pins[0] = 0x15;
Kailang Yang272a5272007-05-14 11:00:38 +02008940}
8941
Kailang Yangccc656c2006-10-17 12:32:26 +02008942/* toggle speaker-output according to the hp-jack state */
Sasha Alexandrc2592492009-06-16 14:52:54 -04008943#define alc883_targa_init_hook alc882_targa_init_hook
8944#define alc883_targa_unsol_event alc882_targa_unsol_event
Jiang zhe368c7a92008-03-04 11:20:33 +01008945
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008946static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
8947{
8948 unsigned int present;
8949
Takashi Iwaid56757a2009-11-18 08:00:14 +01008950 present = snd_hda_jack_detect(codec, 0x18);
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008951 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
8952 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
8953}
8954
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008955static void alc883_clevo_m720_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008956{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008957 struct alc_spec *spec = codec->spec;
8958
8959 spec->autocfg.hp_pins[0] = 0x15;
8960 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008961}
8962
8963static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
8964{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008965 alc_automute_amp(codec);
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008966 alc883_clevo_m720_mic_automute(codec);
8967}
8968
8969static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
Jiang zhe368c7a92008-03-04 11:20:33 +01008970 unsigned int res)
8971{
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008972 switch (res >> 26) {
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008973 case ALC880_MIC_EVENT:
8974 alc883_clevo_m720_mic_automute(codec);
8975 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008976 default:
8977 alc_automute_amp_unsol_event(codec, res);
8978 break;
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008979 }
Jiang zhe368c7a92008-03-04 11:20:33 +01008980}
8981
Jiang zhefb97dc62008-03-06 11:07:11 +01008982/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008983static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
Jiang zhefb97dc62008-03-06 11:07:11 +01008984{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008985 struct alc_spec *spec = codec->spec;
Jiang zhefb97dc62008-03-06 11:07:11 +01008986
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008987 spec->autocfg.hp_pins[0] = 0x14;
8988 spec->autocfg.speaker_pins[0] = 0x15;
Jiang zhefb97dc62008-03-06 11:07:11 +01008989}
8990
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008991static void alc883_haier_w66_setup(struct hda_codec *codec)
Jiang zhefb97dc62008-03-06 11:07:11 +01008992{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008993 struct alc_spec *spec = codec->spec;
Jiang zhefb97dc62008-03-06 11:07:11 +01008994
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008995 spec->autocfg.hp_pins[0] = 0x1b;
8996 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang189609a2007-08-20 11:31:23 +02008997}
8998
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008999static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
9000{
Wu Fengguang864f92b2009-11-18 12:38:02 +08009001 int bits = snd_hda_jack_detect(codec, 0x14) ? HDA_AMP_MUTE : 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009002
Takashi Iwai47fd8302007-08-10 17:11:07 +02009003 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9004 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009005}
9006
9007static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
9008{
Wu Fengguang864f92b2009-11-18 12:38:02 +08009009 int bits = snd_hda_jack_detect(codec, 0x1b) ? HDA_AMP_MUTE : 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009010
Takashi Iwai47fd8302007-08-10 17:11:07 +02009011 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9012 HDA_AMP_MUTE, bits);
9013 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9014 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009015}
9016
9017static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
9018 unsigned int res)
9019{
9020 if ((res >> 26) == ALC880_HP_EVENT)
9021 alc883_lenovo_101e_all_automute(codec);
9022 if ((res >> 26) == ALC880_FRONT_EVENT)
9023 alc883_lenovo_101e_ispeaker_automute(codec);
9024}
9025
Takashi Iwai676a9b52007-08-16 15:23:35 +02009026/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009027static void alc883_acer_aspire_setup(struct hda_codec *codec)
Takashi Iwai676a9b52007-08-16 15:23:35 +02009028{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009029 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02009030
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009031 spec->autocfg.hp_pins[0] = 0x14;
9032 spec->autocfg.speaker_pins[0] = 0x15;
9033 spec->autocfg.speaker_pins[1] = 0x16;
Takashi Iwai676a9b52007-08-16 15:23:35 +02009034}
9035
Kailang Yangd1a991a2007-08-15 16:21:59 +02009036static struct hda_verb alc883_acer_eapd_verbs[] = {
9037 /* HP Pin: output 0 (0x0c) */
9038 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9039 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9040 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9041 /* Front Pin: output 0 (0x0c) */
Takashi Iwai676a9b52007-08-16 15:23:35 +02009042 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9043 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangd1a991a2007-08-15 16:21:59 +02009044 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangd1a991a2007-08-15 16:21:59 +02009045 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
9046 /* eanable EAPD on medion laptop */
9047 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
9048 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
Takashi Iwai676a9b52007-08-16 15:23:35 +02009049 /* enable unsolicited event */
9050 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yangd1a991a2007-08-15 16:21:59 +02009051 { }
9052};
9053
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009054static struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
9055 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9056 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
9057 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9058 { } /* end */
9059};
9060
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009061static void alc888_6st_dell_setup(struct hda_codec *codec)
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009062{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009063 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02009064
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009065 spec->autocfg.hp_pins[0] = 0x1b;
9066 spec->autocfg.speaker_pins[0] = 0x14;
9067 spec->autocfg.speaker_pins[1] = 0x15;
9068 spec->autocfg.speaker_pins[2] = 0x16;
9069 spec->autocfg.speaker_pins[3] = 0x17;
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009070}
9071
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009072static void alc888_lenovo_sky_setup(struct hda_codec *codec)
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009073{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009074 struct alc_spec *spec = codec->spec;
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009075
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009076 spec->autocfg.hp_pins[0] = 0x1b;
9077 spec->autocfg.speaker_pins[0] = 0x14;
9078 spec->autocfg.speaker_pins[1] = 0x15;
9079 spec->autocfg.speaker_pins[2] = 0x16;
9080 spec->autocfg.speaker_pins[3] = 0x17;
9081 spec->autocfg.speaker_pins[4] = 0x1a;
Kailang Yange2757d52008-08-26 13:17:46 +02009082}
9083
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009084static void alc883_vaiott_setup(struct hda_codec *codec)
Guido Günther3e1647c2009-06-05 00:47:26 +02009085{
9086 struct alc_spec *spec = codec->spec;
9087
9088 spec->autocfg.hp_pins[0] = 0x15;
9089 spec->autocfg.speaker_pins[0] = 0x14;
9090 spec->autocfg.speaker_pins[1] = 0x17;
Guido Günther3e1647c2009-06-05 00:47:26 +02009091}
9092
Kailang Yange2757d52008-08-26 13:17:46 +02009093static struct hda_verb alc888_asus_m90v_verbs[] = {
9094 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9095 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9096 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9097 /* enable unsolicited event */
9098 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9099 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9100 { } /* end */
9101};
9102
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009103static void alc883_mode2_setup(struct hda_codec *codec)
Kailang Yange2757d52008-08-26 13:17:46 +02009104{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009105 struct alc_spec *spec = codec->spec;
Kailang Yange2757d52008-08-26 13:17:46 +02009106
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009107 spec->autocfg.hp_pins[0] = 0x1b;
9108 spec->autocfg.speaker_pins[0] = 0x14;
9109 spec->autocfg.speaker_pins[1] = 0x15;
9110 spec->autocfg.speaker_pins[2] = 0x16;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009111 spec->ext_mic.pin = 0x18;
9112 spec->int_mic.pin = 0x19;
9113 spec->ext_mic.mux_idx = 0;
9114 spec->int_mic.mux_idx = 1;
9115 spec->auto_mic = 1;
Kailang Yange2757d52008-08-26 13:17:46 +02009116}
9117
9118static struct hda_verb alc888_asus_eee1601_verbs[] = {
9119 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9120 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9121 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9122 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9123 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9124 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
9125 {0x20, AC_VERB_SET_PROC_COEF, 0x0838},
9126 /* enable unsolicited event */
9127 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9128 { } /* end */
9129};
9130
Kailang Yange2757d52008-08-26 13:17:46 +02009131static void alc883_eee1601_inithook(struct hda_codec *codec)
9132{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009133 struct alc_spec *spec = codec->spec;
9134
9135 spec->autocfg.hp_pins[0] = 0x14;
9136 spec->autocfg.speaker_pins[0] = 0x1b;
9137 alc_automute_pin(codec);
Kailang Yange2757d52008-08-26 13:17:46 +02009138}
9139
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009140static struct hda_verb alc889A_mb31_verbs[] = {
9141 /* Init rear pin (used as headphone output) */
9142 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */
9143 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */
9144 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9145 /* Init line pin (used as output in 4ch and 6ch mode) */
9146 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */
9147 /* Init line 2 pin (used as headphone out by default) */
9148 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */
9149 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
9150 { } /* end */
9151};
9152
9153/* Mute speakers according to the headphone jack state */
9154static void alc889A_mb31_automute(struct hda_codec *codec)
9155{
9156 unsigned int present;
9157
9158 /* Mute only in 2ch or 4ch mode */
9159 if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
9160 == 0x00) {
Wu Fengguang864f92b2009-11-18 12:38:02 +08009161 present = snd_hda_jack_detect(codec, 0x15);
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009162 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9163 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9164 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
9165 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9166 }
9167}
9168
9169static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
9170{
9171 if ((res >> 26) == ALC880_HP_EVENT)
9172 alc889A_mb31_automute(codec);
9173}
9174
Takashi Iwai4953550a2009-06-30 15:28:30 +02009175
Takashi Iwaicb53c622007-08-10 17:21:45 +02009176#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwai4953550a2009-06-30 15:28:30 +02009177#define alc882_loopbacks alc880_loopbacks
Takashi Iwaicb53c622007-08-10 17:21:45 +02009178#endif
9179
Sasha Alexandrdef319f2009-06-16 16:00:15 -04009180/* pcm configuration: identical with ALC880 */
Takashi Iwai4953550a2009-06-30 15:28:30 +02009181#define alc882_pcm_analog_playback alc880_pcm_analog_playback
9182#define alc882_pcm_analog_capture alc880_pcm_analog_capture
9183#define alc882_pcm_digital_playback alc880_pcm_digital_playback
9184#define alc882_pcm_digital_capture alc880_pcm_digital_capture
9185
9186static hda_nid_t alc883_slave_dig_outs[] = {
9187 ALC1200_DIGOUT_NID, 0,
9188};
9189
9190static hda_nid_t alc1200_slave_dig_outs[] = {
9191 ALC883_DIGOUT_NID, 0,
9192};
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009193
9194/*
9195 * configuration and preset
9196 */
Takashi Iwai4953550a2009-06-30 15:28:30 +02009197static const char *alc882_models[ALC882_MODEL_LAST] = {
9198 [ALC882_3ST_DIG] = "3stack-dig",
9199 [ALC882_6ST_DIG] = "6stack-dig",
9200 [ALC882_ARIMA] = "arima",
9201 [ALC882_W2JC] = "w2jc",
9202 [ALC882_TARGA] = "targa",
9203 [ALC882_ASUS_A7J] = "asus-a7j",
9204 [ALC882_ASUS_A7M] = "asus-a7m",
9205 [ALC885_MACPRO] = "macpro",
9206 [ALC885_MB5] = "mb5",
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009207 [ALC885_MACMINI3] = "macmini3",
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08009208 [ALC885_MBA21] = "mba21",
Takashi Iwai4953550a2009-06-30 15:28:30 +02009209 [ALC885_MBP3] = "mbp3",
9210 [ALC885_IMAC24] = "imac24",
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009211 [ALC885_IMAC91] = "imac91",
Takashi Iwai4953550a2009-06-30 15:28:30 +02009212 [ALC883_3ST_2ch_DIG] = "3stack-2ch-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009213 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
9214 [ALC883_3ST_6ch] = "3stack-6ch",
Takashi Iwai4953550a2009-06-30 15:28:30 +02009215 [ALC883_6ST_DIG] = "alc883-6stack-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009216 [ALC883_TARGA_DIG] = "targa-dig",
9217 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
David Heidelberger64a8be72009-06-08 16:15:18 +02009218 [ALC883_TARGA_8ch_DIG] = "targa-8ch-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009219 [ALC883_ACER] = "acer",
Tobin Davis2880a862007-08-07 11:50:26 +02009220 [ALC883_ACER_ASPIRE] = "acer-aspire",
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009221 [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g",
Takashi Iwaib1a91462009-06-21 10:56:44 +02009222 [ALC888_ACER_ASPIRE_6530G] = "acer-aspire-6530g",
Hector Martin3b315d72009-06-02 10:54:19 +02009223 [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g",
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009224 [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009225 [ALC883_MEDION] = "medion",
Kailang Yang272a5272007-05-14 11:00:38 +02009226 [ALC883_MEDION_MD2] = "medion-md2",
Maurus Cuelenaere7ad7b212010-04-06 18:12:52 +02009227 [ALC883_MEDION_WIM2160] = "medion-wim2160",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009228 [ALC883_LAPTOP_EAPD] = "laptop-eapd",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009229 [ALC883_LENOVO_101E_2ch] = "lenovo-101e",
Kailang Yang272a5272007-05-14 11:00:38 +02009230 [ALC883_LENOVO_NB0763] = "lenovo-nb0763",
9231 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
Kailang Yange2757d52008-08-26 13:17:46 +02009232 [ALC888_LENOVO_SKY] = "lenovo-sky",
Kailang Yang189609a2007-08-20 11:31:23 +02009233 [ALC883_HAIER_W66] = "haier-w66",
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009234 [ALC888_3ST_HP] = "3stack-hp",
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009235 [ALC888_6ST_DELL] = "6stack-dell",
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01009236 [ALC883_MITAC] = "mitac",
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04309237 [ALC883_CLEVO_M540R] = "clevo-m540r",
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009238 [ALC883_CLEVO_M720] = "clevo-m720",
Jiang zhefb97dc62008-03-06 11:07:11 +01009239 [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009240 [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
Jiang zhe17bba1b2008-06-04 12:11:07 +02009241 [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009242 [ALC889A_INTEL] = "intel-alc889a",
9243 [ALC889_INTEL] = "intel-x58",
Wu Fengguang3ab90932008-11-17 09:51:09 +01009244 [ALC1200_ASUS_P5Q] = "asus-p5q",
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009245 [ALC889A_MB31] = "mb31",
Guido Günther3e1647c2009-06-05 00:47:26 +02009246 [ALC883_SONY_VAIO_TT] = "sony-vaio-tt",
Takashi Iwai4953550a2009-06-30 15:28:30 +02009247 [ALC882_AUTO] = "auto",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009248};
9249
Takashi Iwai4953550a2009-06-30 15:28:30 +02009250static struct snd_pci_quirk alc882_cfg_tbl[] = {
9251 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
9252
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009253 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
Takashi Iwai69e50282008-11-03 10:07:43 +01009254 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
Takashi Iwai9b6682f2009-03-23 22:50:52 +01009255 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009256 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
9257 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
Jaroslav Kysela0b18cb12008-07-28 17:07:07 +02009258 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009259 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
9260 ALC888_ACER_ASPIRE_4930G),
Lukasz Wojnilowicza8e4f9d2009-01-08 12:00:49 +01009261 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
Takashi Iwai83dd7402009-11-24 08:57:53 +01009262 ALC888_ACER_ASPIRE_4930G),
Hector Martin3b315d72009-06-02 10:54:19 +02009263 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
9264 ALC888_ACER_ASPIRE_8930G),
Takashi Iwaie46b0c82009-06-13 10:16:43 +02009265 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
9266 ALC888_ACER_ASPIRE_8930G),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009267 SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
9268 SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
Lukasz Wojnilowicza8e4f9d2009-01-08 12:00:49 +01009269 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
Takashi Iwaidde65352009-06-25 08:25:35 +02009270 ALC888_ACER_ASPIRE_6530G),
Juan Jesus Garcia de Soriacc374c42009-02-23 08:11:59 +01009271 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
Tony Vroond2fd4b02009-06-21 00:40:10 +01009272 ALC888_ACER_ASPIRE_6530G),
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009273 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
9274 ALC888_ACER_ASPIRE_7730G),
Takashi Iwai22b530e2009-05-13 11:32:52 +02009275 /* default Acer -- disabled as it causes more problems.
9276 * model=auto should work fine now
9277 */
9278 /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
Takashi Iwai4953550a2009-06-30 15:28:30 +02009279
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009280 SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009281
Tobin Davisfebe3372007-06-12 11:27:46 +02009282 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009283 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
9284 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
Herton Ronaldo Krzesinski5d85f8d2008-03-20 12:13:46 +01009285 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
Chris Bagwell06bf3e12009-01-01 10:32:08 +01009286 SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
Herton Ronaldo Krzesinski7ec30f02009-03-04 14:22:52 -03009287 SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009288
9289 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
9290 SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
9291 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
Kailang Yanga01c30c2008-10-15 11:14:58 +02009292 SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009293 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
9294 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
9295 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009296 SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
Mackenzie Morgan44a678d2009-02-10 17:13:43 +01009297 SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
Wu Fengguang3ab90932008-11-17 09:51:09 +01009298 SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
Kailang Yange2757d52008-08-26 13:17:46 +02009299 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009300
9301 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
Travis Place97ec7102008-05-23 18:31:46 +02009302 SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009303 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
Luke Yelavich2de686d2009-01-16 15:08:02 +11009304 SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009305 SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
9306 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
Kailang Yange2757d52008-08-26 13:17:46 +02009307 SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009308 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009309 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
9310
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009311 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
9312 SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
9313 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009314 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
Takashi Iwai2fef62c2009-12-18 08:48:42 +01009315 SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009316 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009317 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
Pascal Terjan82808232008-03-04 11:33:28 +01009318 SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009319 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
9320 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
9321 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
9322 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
9323 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
9324 SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
William Westonb1e44222009-07-08 01:10:05 -07009325 SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009326 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
9327 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
9328 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
Anisse Astierb43f6e52010-03-10 19:17:46 +01009329 SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
David Heidelberger64a8be72009-06-08 16:15:18 +02009330 SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009331 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
9332 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
Tobin Davis799f88a2007-05-29 14:29:08 +02009333 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
Takashi Iwaiee095432008-11-25 15:03:38 +01009334 SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
Herton Ronaldo Krzesinski86d34b72008-03-18 09:27:59 +01009335 SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
Leonard Norrgard2a296cb2007-01-08 11:28:22 +01009336 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
Tobin Davis2dcd5222007-07-10 17:04:57 +02009337 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
Sasha Alexandrdf01b8a2009-06-16 14:46:17 -04009338 SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
Anisse Astierb43f6e52010-03-10 19:17:46 +01009339 SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009340 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
William Westonb1e44222009-07-08 01:10:05 -07009341 SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009342
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009343 SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009344 SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
9345 SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04309346 SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
Takashi Iwaidea0a502009-02-09 17:14:52 +01009347 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
Daniel T Chene60623b2007-05-29 03:41:55 -04009348 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009349 /* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009350 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
Takashi Iwaibfb53032009-04-14 14:51:04 +02009351 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
Takashi Iwaif67d8172009-02-04 23:30:19 +01009352 ALC883_FUJITSU_PI2515),
Takashi Iwaibfb53032009-04-14 14:51:04 +02009353 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009354 ALC888_FUJITSU_XA3530),
Kailang Yang272a5272007-05-14 11:00:38 +02009355 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
Kailang Yang272a5272007-05-14 11:00:38 +02009356 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009357 SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
9358 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
Kailang Yange2757d52008-08-26 13:17:46 +02009359 SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
Kailang Yang272a5272007-05-14 11:00:38 +02009360 SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
Takashi Iwai959973b2008-11-05 11:30:56 +01009361 SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
Andrew Paprocki0b167bf2008-02-03 10:15:44 +01009362 SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
Kailang Yang189609a2007-08-20 11:31:23 +02009363 SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009364
Jiang zhe17bba1b2008-06-04 12:11:07 +02009365 SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
9366 SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
Luke Yelavich2de686d2009-01-16 15:08:02 +11009367 SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009368 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
9369 SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
9370 SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
Daniel T Chen572c0e32010-03-14 23:44:03 -04009371 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009372
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009373 {}
9374};
9375
Takashi Iwai4953550a2009-06-30 15:28:30 +02009376/* codec SSID table for Intel Mac */
9377static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
9378 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
9379 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
9380 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
9381 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
9382 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
9383 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
9384 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
9385 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
9386 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
9387 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009388 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009389 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
Daniel T Chen46ef6ec2009-11-11 14:32:10 -05009390 /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
9391 * so apparently no perfect solution yet
Takashi Iwai4953550a2009-06-30 15:28:30 +02009392 */
9393 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
Daniel T Chen46ef6ec2009-11-11 14:32:10 -05009394 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009395 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009396 {} /* terminator */
Wu Fengguangf3cd3f52009-04-02 19:44:18 +08009397};
9398
Takashi Iwai4953550a2009-06-30 15:28:30 +02009399static struct alc_config_preset alc882_presets[] = {
9400 [ALC882_3ST_DIG] = {
9401 .mixers = { alc882_base_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009402 .init_verbs = { alc882_base_init_verbs,
9403 alc882_adc1_init_verbs },
Takashi Iwai4953550a2009-06-30 15:28:30 +02009404 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9405 .dac_nids = alc882_dac_nids,
9406 .dig_out_nid = ALC882_DIGOUT_NID,
9407 .dig_in_nid = ALC882_DIGIN_NID,
9408 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9409 .channel_mode = alc882_ch_modes,
9410 .need_dac_fix = 1,
9411 .input_mux = &alc882_capture_source,
9412 },
9413 [ALC882_6ST_DIG] = {
9414 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009415 .init_verbs = { alc882_base_init_verbs,
9416 alc882_adc1_init_verbs },
Takashi Iwai4953550a2009-06-30 15:28:30 +02009417 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9418 .dac_nids = alc882_dac_nids,
9419 .dig_out_nid = ALC882_DIGOUT_NID,
9420 .dig_in_nid = ALC882_DIGIN_NID,
9421 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
9422 .channel_mode = alc882_sixstack_modes,
9423 .input_mux = &alc882_capture_source,
9424 },
9425 [ALC882_ARIMA] = {
9426 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009427 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9428 alc882_eapd_verbs },
Takashi Iwai4953550a2009-06-30 15:28:30 +02009429 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9430 .dac_nids = alc882_dac_nids,
9431 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
9432 .channel_mode = alc882_sixstack_modes,
9433 .input_mux = &alc882_capture_source,
9434 },
9435 [ALC882_W2JC] = {
9436 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009437 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9438 alc882_eapd_verbs, alc880_gpio1_init_verbs },
Takashi Iwai4953550a2009-06-30 15:28:30 +02009439 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9440 .dac_nids = alc882_dac_nids,
9441 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
9442 .channel_mode = alc880_threestack_modes,
9443 .need_dac_fix = 1,
9444 .input_mux = &alc882_capture_source,
9445 .dig_out_nid = ALC882_DIGOUT_NID,
9446 },
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08009447 [ALC885_MBA21] = {
9448 .mixers = { alc885_mba21_mixer },
9449 .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
9450 .num_dacs = 2,
9451 .dac_nids = alc882_dac_nids,
9452 .channel_mode = alc885_mba21_ch_modes,
9453 .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
9454 .input_mux = &alc882_capture_source,
9455 .unsol_event = alc_automute_amp_unsol_event,
9456 .setup = alc885_mba21_setup,
9457 .init_hook = alc_automute_amp,
9458 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02009459 [ALC885_MBP3] = {
9460 .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
9461 .init_verbs = { alc885_mbp3_init_verbs,
9462 alc880_gpio1_init_verbs },
Takashi Iwaibe0ae922009-08-31 08:27:10 +02009463 .num_dacs = 2,
Takashi Iwai4953550a2009-06-30 15:28:30 +02009464 .dac_nids = alc882_dac_nids,
Takashi Iwaibe0ae922009-08-31 08:27:10 +02009465 .hp_nid = 0x04,
9466 .channel_mode = alc885_mbp_4ch_modes,
9467 .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
Takashi Iwai4953550a2009-06-30 15:28:30 +02009468 .input_mux = &alc882_capture_source,
9469 .dig_out_nid = ALC882_DIGOUT_NID,
9470 .dig_in_nid = ALC882_DIGIN_NID,
9471 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009472 .setup = alc885_mbp3_setup,
9473 .init_hook = alc_automute_amp,
Takashi Iwai4953550a2009-06-30 15:28:30 +02009474 },
9475 [ALC885_MB5] = {
9476 .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
9477 .init_verbs = { alc885_mb5_init_verbs,
9478 alc880_gpio1_init_verbs },
9479 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9480 .dac_nids = alc882_dac_nids,
9481 .channel_mode = alc885_mb5_6ch_modes,
9482 .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
9483 .input_mux = &mb5_capture_source,
9484 .dig_out_nid = ALC882_DIGOUT_NID,
9485 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009486 .unsol_event = alc_automute_amp_unsol_event,
9487 .setup = alc885_mb5_setup,
9488 .init_hook = alc_automute_amp,
Takashi Iwai4953550a2009-06-30 15:28:30 +02009489 },
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009490 [ALC885_MACMINI3] = {
9491 .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
9492 .init_verbs = { alc885_macmini3_init_verbs,
9493 alc880_gpio1_init_verbs },
9494 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9495 .dac_nids = alc882_dac_nids,
9496 .channel_mode = alc885_macmini3_6ch_modes,
9497 .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
9498 .input_mux = &macmini3_capture_source,
9499 .dig_out_nid = ALC882_DIGOUT_NID,
9500 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009501 .unsol_event = alc_automute_amp_unsol_event,
9502 .setup = alc885_macmini3_setup,
9503 .init_hook = alc_automute_amp,
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009504 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02009505 [ALC885_MACPRO] = {
9506 .mixers = { alc882_macpro_mixer },
9507 .init_verbs = { alc882_macpro_init_verbs },
9508 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9509 .dac_nids = alc882_dac_nids,
9510 .dig_out_nid = ALC882_DIGOUT_NID,
9511 .dig_in_nid = ALC882_DIGIN_NID,
9512 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9513 .channel_mode = alc882_ch_modes,
9514 .input_mux = &alc882_capture_source,
9515 .init_hook = alc885_macpro_init_hook,
9516 },
9517 [ALC885_IMAC24] = {
9518 .mixers = { alc885_imac24_mixer },
9519 .init_verbs = { alc885_imac24_init_verbs },
9520 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9521 .dac_nids = alc882_dac_nids,
9522 .dig_out_nid = ALC882_DIGOUT_NID,
9523 .dig_in_nid = ALC882_DIGIN_NID,
9524 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9525 .channel_mode = alc882_ch_modes,
9526 .input_mux = &alc882_capture_source,
9527 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009528 .setup = alc885_imac24_setup,
Takashi Iwai4953550a2009-06-30 15:28:30 +02009529 .init_hook = alc885_imac24_init_hook,
9530 },
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009531 [ALC885_IMAC91] = {
9532 .mixers = { alc885_imac91_mixer, alc882_chmode_mixer },
9533 .init_verbs = { alc885_imac91_init_verbs,
9534 alc880_gpio1_init_verbs },
9535 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9536 .dac_nids = alc882_dac_nids,
9537 .channel_mode = alc885_mbp_4ch_modes,
9538 .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
9539 .input_mux = &alc882_capture_source,
9540 .dig_out_nid = ALC882_DIGOUT_NID,
9541 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009542 .unsol_event = alc_automute_amp_unsol_event,
9543 .setup = alc885_imac91_setup,
9544 .init_hook = alc_automute_amp,
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009545 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02009546 [ALC882_TARGA] = {
9547 .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009548 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
Takashi Iwai31909b82009-07-10 12:33:48 +02009549 alc880_gpio3_init_verbs, alc882_targa_verbs},
Takashi Iwai4953550a2009-06-30 15:28:30 +02009550 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9551 .dac_nids = alc882_dac_nids,
9552 .dig_out_nid = ALC882_DIGOUT_NID,
9553 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
9554 .adc_nids = alc882_adc_nids,
9555 .capsrc_nids = alc882_capsrc_nids,
9556 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
9557 .channel_mode = alc882_3ST_6ch_modes,
9558 .need_dac_fix = 1,
9559 .input_mux = &alc882_capture_source,
9560 .unsol_event = alc882_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009561 .setup = alc882_targa_setup,
9562 .init_hook = alc882_targa_automute,
Takashi Iwai4953550a2009-06-30 15:28:30 +02009563 },
9564 [ALC882_ASUS_A7J] = {
9565 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009566 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9567 alc882_asus_a7j_verbs},
Takashi Iwai4953550a2009-06-30 15:28:30 +02009568 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9569 .dac_nids = alc882_dac_nids,
9570 .dig_out_nid = ALC882_DIGOUT_NID,
9571 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
9572 .adc_nids = alc882_adc_nids,
9573 .capsrc_nids = alc882_capsrc_nids,
9574 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
9575 .channel_mode = alc882_3ST_6ch_modes,
9576 .need_dac_fix = 1,
9577 .input_mux = &alc882_capture_source,
9578 },
9579 [ALC882_ASUS_A7M] = {
9580 .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009581 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9582 alc882_eapd_verbs, alc880_gpio1_init_verbs,
Takashi Iwai4953550a2009-06-30 15:28:30 +02009583 alc882_asus_a7m_verbs },
9584 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9585 .dac_nids = alc882_dac_nids,
9586 .dig_out_nid = ALC882_DIGOUT_NID,
9587 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
9588 .channel_mode = alc880_threestack_modes,
9589 .need_dac_fix = 1,
9590 .input_mux = &alc882_capture_source,
9591 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009592 [ALC883_3ST_2ch_DIG] = {
9593 .mixers = { alc883_3ST_2ch_mixer },
9594 .init_verbs = { alc883_init_verbs },
9595 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9596 .dac_nids = alc883_dac_nids,
9597 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009598 .dig_in_nid = ALC883_DIGIN_NID,
9599 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9600 .channel_mode = alc883_3ST_2ch_modes,
9601 .input_mux = &alc883_capture_source,
9602 },
9603 [ALC883_3ST_6ch_DIG] = {
9604 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9605 .init_verbs = { alc883_init_verbs },
9606 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9607 .dac_nids = alc883_dac_nids,
9608 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009609 .dig_in_nid = ALC883_DIGIN_NID,
9610 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9611 .channel_mode = alc883_3ST_6ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02009612 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009613 .input_mux = &alc883_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02009614 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009615 [ALC883_3ST_6ch] = {
9616 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9617 .init_verbs = { alc883_init_verbs },
9618 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9619 .dac_nids = alc883_dac_nids,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009620 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9621 .channel_mode = alc883_3ST_6ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02009622 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009623 .input_mux = &alc883_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02009624 },
Jiang zhe17bba1b2008-06-04 12:11:07 +02009625 [ALC883_3ST_6ch_INTEL] = {
9626 .mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
9627 .init_verbs = { alc883_init_verbs },
9628 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9629 .dac_nids = alc883_dac_nids,
9630 .dig_out_nid = ALC883_DIGOUT_NID,
9631 .dig_in_nid = ALC883_DIGIN_NID,
Wu Fengguangf3cd3f52009-04-02 19:44:18 +08009632 .slave_dig_outs = alc883_slave_dig_outs,
Jiang zhe17bba1b2008-06-04 12:11:07 +02009633 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
9634 .channel_mode = alc883_3ST_6ch_intel_modes,
9635 .need_dac_fix = 1,
9636 .input_mux = &alc883_3stack_6ch_intel,
9637 },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009638 [ALC889A_INTEL] = {
9639 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +02009640 .init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
9641 alc_hp15_unsol_verbs },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009642 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9643 .dac_nids = alc883_dac_nids,
9644 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
9645 .adc_nids = alc889_adc_nids,
9646 .dig_out_nid = ALC883_DIGOUT_NID,
9647 .dig_in_nid = ALC883_DIGIN_NID,
9648 .slave_dig_outs = alc883_slave_dig_outs,
9649 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
9650 .channel_mode = alc889_8ch_intel_modes,
9651 .capsrc_nids = alc889_capsrc_nids,
9652 .input_mux = &alc889_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009653 .setup = alc889_automute_setup,
9654 .init_hook = alc_automute_amp,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009655 .unsol_event = alc_automute_amp_unsol_event,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009656 .need_dac_fix = 1,
9657 },
9658 [ALC889_INTEL] = {
9659 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
9660 .init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009661 alc889_eapd_verbs, alc_hp15_unsol_verbs},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009662 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9663 .dac_nids = alc883_dac_nids,
9664 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
9665 .adc_nids = alc889_adc_nids,
9666 .dig_out_nid = ALC883_DIGOUT_NID,
9667 .dig_in_nid = ALC883_DIGIN_NID,
9668 .slave_dig_outs = alc883_slave_dig_outs,
9669 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
9670 .channel_mode = alc889_8ch_intel_modes,
9671 .capsrc_nids = alc889_capsrc_nids,
9672 .input_mux = &alc889_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009673 .setup = alc889_automute_setup,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009674 .init_hook = alc889_intel_init_hook,
9675 .unsol_event = alc_automute_amp_unsol_event,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009676 .need_dac_fix = 1,
9677 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009678 [ALC883_6ST_DIG] = {
9679 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
9680 .init_verbs = { alc883_init_verbs },
9681 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9682 .dac_nids = alc883_dac_nids,
9683 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009684 .dig_in_nid = ALC883_DIGIN_NID,
9685 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
9686 .channel_mode = alc883_sixstack_modes,
9687 .input_mux = &alc883_capture_source,
9688 },
Kailang Yangccc656c2006-10-17 12:32:26 +02009689 [ALC883_TARGA_DIG] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -04009690 .mixers = { alc883_targa_mixer, alc883_chmode_mixer },
David Heidelberger005b1072009-07-09 18:45:46 +02009691 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
9692 alc883_targa_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +02009693 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9694 .dac_nids = alc883_dac_nids,
9695 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yangccc656c2006-10-17 12:32:26 +02009696 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9697 .channel_mode = alc883_3ST_6ch_modes,
9698 .need_dac_fix = 1,
9699 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -04009700 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009701 .setup = alc882_targa_setup,
9702 .init_hook = alc882_targa_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +02009703 },
9704 [ALC883_TARGA_2ch_DIG] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -04009705 .mixers = { alc883_targa_2ch_mixer},
David Heidelberger005b1072009-07-09 18:45:46 +02009706 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
9707 alc883_targa_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +02009708 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9709 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01009710 .adc_nids = alc883_adc_nids_alt,
9711 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +01009712 .capsrc_nids = alc883_capsrc_nids,
Kailang Yangccc656c2006-10-17 12:32:26 +02009713 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yangccc656c2006-10-17 12:32:26 +02009714 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9715 .channel_mode = alc883_3ST_2ch_modes,
9716 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -04009717 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009718 .setup = alc882_targa_setup,
9719 .init_hook = alc882_targa_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +02009720 },
David Heidelberger64a8be72009-06-08 16:15:18 +02009721 [ALC883_TARGA_8ch_DIG] = {
Takashi Iwaib99dba32009-09-17 18:23:00 +02009722 .mixers = { alc883_targa_mixer, alc883_targa_8ch_mixer,
9723 alc883_chmode_mixer },
David Heidelberger64a8be72009-06-08 16:15:18 +02009724 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
Sasha Alexandrc2592492009-06-16 14:52:54 -04009725 alc883_targa_verbs },
David Heidelberger64a8be72009-06-08 16:15:18 +02009726 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9727 .dac_nids = alc883_dac_nids,
9728 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9729 .adc_nids = alc883_adc_nids_rev,
9730 .capsrc_nids = alc883_capsrc_nids_rev,
9731 .dig_out_nid = ALC883_DIGOUT_NID,
9732 .dig_in_nid = ALC883_DIGIN_NID,
9733 .num_channel_mode = ARRAY_SIZE(alc883_4ST_8ch_modes),
9734 .channel_mode = alc883_4ST_8ch_modes,
9735 .need_dac_fix = 1,
9736 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -04009737 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009738 .setup = alc882_targa_setup,
9739 .init_hook = alc882_targa_automute,
David Heidelberger64a8be72009-06-08 16:15:18 +02009740 },
Vladimir Avdoninbab282b92006-08-22 13:31:58 +02009741 [ALC883_ACER] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +02009742 .mixers = { alc883_base_mixer },
Vladimir Avdoninbab282b92006-08-22 13:31:58 +02009743 /* On TravelMate laptops, GPIO 0 enables the internal speaker
9744 * and the headphone jack. Turn this on and rely on the
9745 * standard mute methods whenever the user wants to turn
9746 * these outputs off.
9747 */
9748 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
9749 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9750 .dac_nids = alc883_dac_nids,
Vladimir Avdoninbab282b92006-08-22 13:31:58 +02009751 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9752 .channel_mode = alc883_3ST_2ch_modes,
9753 .input_mux = &alc883_capture_source,
9754 },
Tobin Davis2880a862007-08-07 11:50:26 +02009755 [ALC883_ACER_ASPIRE] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +02009756 .mixers = { alc883_acer_aspire_mixer },
Kailang Yangd1a991a2007-08-15 16:21:59 +02009757 .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
Tobin Davis2880a862007-08-07 11:50:26 +02009758 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9759 .dac_nids = alc883_dac_nids,
9760 .dig_out_nid = ALC883_DIGOUT_NID,
Tobin Davis2880a862007-08-07 11:50:26 +02009761 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9762 .channel_mode = alc883_3ST_2ch_modes,
9763 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009764 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009765 .setup = alc883_acer_aspire_setup,
9766 .init_hook = alc_automute_amp,
Kailang Yangd1a991a2007-08-15 16:21:59 +02009767 },
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009768 [ALC888_ACER_ASPIRE_4930G] = {
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009769 .mixers = { alc888_base_mixer,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009770 alc883_chmode_mixer },
9771 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
9772 alc888_acer_aspire_4930g_verbs },
9773 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9774 .dac_nids = alc883_dac_nids,
9775 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9776 .adc_nids = alc883_adc_nids_rev,
9777 .capsrc_nids = alc883_capsrc_nids_rev,
9778 .dig_out_nid = ALC883_DIGOUT_NID,
9779 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9780 .channel_mode = alc883_3ST_6ch_modes,
9781 .need_dac_fix = 1,
Łukasz Wojniłowicz973b8cb2010-01-24 14:12:37 +01009782 .const_channel_count = 6,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009783 .num_mux_defs =
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009784 ARRAY_SIZE(alc888_2_capture_sources),
9785 .input_mux = alc888_2_capture_sources,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009786 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009787 .setup = alc888_acer_aspire_4930g_setup,
9788 .init_hook = alc_automute_amp,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009789 },
Tony Vroond2fd4b02009-06-21 00:40:10 +01009790 [ALC888_ACER_ASPIRE_6530G] = {
9791 .mixers = { alc888_acer_aspire_6530_mixer },
9792 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
9793 alc888_acer_aspire_6530g_verbs },
9794 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9795 .dac_nids = alc883_dac_nids,
9796 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9797 .adc_nids = alc883_adc_nids_rev,
9798 .capsrc_nids = alc883_capsrc_nids_rev,
9799 .dig_out_nid = ALC883_DIGOUT_NID,
9800 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9801 .channel_mode = alc883_3ST_2ch_modes,
9802 .num_mux_defs =
9803 ARRAY_SIZE(alc888_2_capture_sources),
9804 .input_mux = alc888_acer_aspire_6530_sources,
9805 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009806 .setup = alc888_acer_aspire_6530g_setup,
9807 .init_hook = alc_automute_amp,
Tony Vroond2fd4b02009-06-21 00:40:10 +01009808 },
Hector Martin3b315d72009-06-02 10:54:19 +02009809 [ALC888_ACER_ASPIRE_8930G] = {
Hector Martin556eea92009-12-20 22:51:23 +01009810 .mixers = { alc889_acer_aspire_8930g_mixer,
Hector Martin3b315d72009-06-02 10:54:19 +02009811 alc883_chmode_mixer },
9812 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
Hector Martin0f86a222009-12-20 22:51:18 +01009813 alc889_acer_aspire_8930g_verbs,
9814 alc889_eapd_verbs},
Hector Martin3b315d72009-06-02 10:54:19 +02009815 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9816 .dac_nids = alc883_dac_nids,
Hector Martin018df412009-06-04 00:13:40 +02009817 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
9818 .adc_nids = alc889_adc_nids,
9819 .capsrc_nids = alc889_capsrc_nids,
Hector Martin3b315d72009-06-02 10:54:19 +02009820 .dig_out_nid = ALC883_DIGOUT_NID,
9821 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9822 .channel_mode = alc883_3ST_6ch_modes,
9823 .need_dac_fix = 1,
9824 .const_channel_count = 6,
9825 .num_mux_defs =
Hector Martin018df412009-06-04 00:13:40 +02009826 ARRAY_SIZE(alc889_capture_sources),
9827 .input_mux = alc889_capture_sources,
Hector Martin3b315d72009-06-02 10:54:19 +02009828 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009829 .setup = alc889_acer_aspire_8930g_setup,
9830 .init_hook = alc_automute_amp,
Hector Martinf5de24b2009-12-20 22:51:31 +01009831#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05009832 .power_hook = alc_power_eapd,
Hector Martinf5de24b2009-12-20 22:51:31 +01009833#endif
Hector Martin3b315d72009-06-02 10:54:19 +02009834 },
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009835 [ALC888_ACER_ASPIRE_7730G] = {
9836 .mixers = { alc883_3ST_6ch_mixer,
9837 alc883_chmode_mixer },
9838 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
9839 alc888_acer_aspire_7730G_verbs },
9840 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9841 .dac_nids = alc883_dac_nids,
9842 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9843 .adc_nids = alc883_adc_nids_rev,
9844 .capsrc_nids = alc883_capsrc_nids_rev,
9845 .dig_out_nid = ALC883_DIGOUT_NID,
9846 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9847 .channel_mode = alc883_3ST_6ch_modes,
9848 .need_dac_fix = 1,
9849 .const_channel_count = 6,
9850 .input_mux = &alc883_capture_source,
9851 .unsol_event = alc_automute_amp_unsol_event,
9852 .setup = alc888_acer_aspire_6530g_setup,
9853 .init_hook = alc_automute_amp,
9854 },
Tobin Davisc07584c2006-10-13 12:32:16 +02009855 [ALC883_MEDION] = {
9856 .mixers = { alc883_fivestack_mixer,
9857 alc883_chmode_mixer },
9858 .init_verbs = { alc883_init_verbs,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009859 alc883_medion_eapd_verbs },
Tobin Davisc07584c2006-10-13 12:32:16 +02009860 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9861 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01009862 .adc_nids = alc883_adc_nids_alt,
9863 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +01009864 .capsrc_nids = alc883_capsrc_nids,
Tobin Davisc07584c2006-10-13 12:32:16 +02009865 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
9866 .channel_mode = alc883_sixstack_modes,
9867 .input_mux = &alc883_capture_source,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009868 },
Kailang Yang272a5272007-05-14 11:00:38 +02009869 [ALC883_MEDION_MD2] = {
9870 .mixers = { alc883_medion_md2_mixer},
9871 .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs},
9872 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9873 .dac_nids = alc883_dac_nids,
9874 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang272a5272007-05-14 11:00:38 +02009875 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9876 .channel_mode = alc883_3ST_2ch_modes,
9877 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009878 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009879 .setup = alc883_medion_md2_setup,
9880 .init_hook = alc_automute_amp,
Kailang Yangea1fb292008-08-26 12:58:38 +02009881 },
Maurus Cuelenaere7ad7b212010-04-06 18:12:52 +02009882 [ALC883_MEDION_WIM2160] = {
9883 .mixers = { alc883_medion_wim2160_mixer },
9884 .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs },
9885 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9886 .dac_nids = alc883_dac_nids,
9887 .dig_out_nid = ALC883_DIGOUT_NID,
9888 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
9889 .adc_nids = alc883_adc_nids,
9890 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9891 .channel_mode = alc883_3ST_2ch_modes,
9892 .input_mux = &alc883_capture_source,
9893 .unsol_event = alc_automute_amp_unsol_event,
9894 .setup = alc883_medion_wim2160_setup,
9895 .init_hook = alc_automute_amp,
9896 },
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009897 [ALC883_LAPTOP_EAPD] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +02009898 .mixers = { alc883_base_mixer },
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009899 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
9900 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9901 .dac_nids = alc883_dac_nids,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009902 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9903 .channel_mode = alc883_3ST_2ch_modes,
9904 .input_mux = &alc883_capture_source,
9905 },
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04309906 [ALC883_CLEVO_M540R] = {
9907 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9908 .init_verbs = { alc883_init_verbs, alc883_clevo_m540r_verbs },
9909 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9910 .dac_nids = alc883_dac_nids,
9911 .dig_out_nid = ALC883_DIGOUT_NID,
9912 .dig_in_nid = ALC883_DIGIN_NID,
9913 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_clevo_modes),
9914 .channel_mode = alc883_3ST_6ch_clevo_modes,
9915 .need_dac_fix = 1,
9916 .input_mux = &alc883_capture_source,
9917 /* This machine has the hardware HP auto-muting, thus
9918 * we need no software mute via unsol event
9919 */
9920 },
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009921 [ALC883_CLEVO_M720] = {
9922 .mixers = { alc883_clevo_m720_mixer },
9923 .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
Jiang zhe368c7a92008-03-04 11:20:33 +01009924 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9925 .dac_nids = alc883_dac_nids,
9926 .dig_out_nid = ALC883_DIGOUT_NID,
9927 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9928 .channel_mode = alc883_3ST_2ch_modes,
9929 .input_mux = &alc883_capture_source,
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009930 .unsol_event = alc883_clevo_m720_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009931 .setup = alc883_clevo_m720_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009932 .init_hook = alc883_clevo_m720_init_hook,
Jiang zhe368c7a92008-03-04 11:20:33 +01009933 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009934 [ALC883_LENOVO_101E_2ch] = {
9935 .mixers = { alc883_lenovo_101e_2ch_mixer},
9936 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
9937 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9938 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01009939 .adc_nids = alc883_adc_nids_alt,
9940 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +01009941 .capsrc_nids = alc883_capsrc_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009942 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9943 .channel_mode = alc883_3ST_2ch_modes,
9944 .input_mux = &alc883_lenovo_101e_capture_source,
9945 .unsol_event = alc883_lenovo_101e_unsol_event,
9946 .init_hook = alc883_lenovo_101e_all_automute,
9947 },
Kailang Yang272a5272007-05-14 11:00:38 +02009948 [ALC883_LENOVO_NB0763] = {
9949 .mixers = { alc883_lenovo_nb0763_mixer },
9950 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
9951 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9952 .dac_nids = alc883_dac_nids,
Kailang Yang272a5272007-05-14 11:00:38 +02009953 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9954 .channel_mode = alc883_3ST_2ch_modes,
9955 .need_dac_fix = 1,
9956 .input_mux = &alc883_lenovo_nb0763_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009957 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009958 .setup = alc883_medion_md2_setup,
9959 .init_hook = alc_automute_amp,
Kailang Yang272a5272007-05-14 11:00:38 +02009960 },
9961 [ALC888_LENOVO_MS7195_DIG] = {
9962 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9963 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
9964 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9965 .dac_nids = alc883_dac_nids,
9966 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang272a5272007-05-14 11:00:38 +02009967 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9968 .channel_mode = alc883_3ST_6ch_modes,
9969 .need_dac_fix = 1,
9970 .input_mux = &alc883_capture_source,
9971 .unsol_event = alc883_lenovo_ms7195_unsol_event,
9972 .init_hook = alc888_lenovo_ms7195_front_automute,
Kailang Yang189609a2007-08-20 11:31:23 +02009973 },
9974 [ALC883_HAIER_W66] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -04009975 .mixers = { alc883_targa_2ch_mixer},
Kailang Yang189609a2007-08-20 11:31:23 +02009976 .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
9977 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9978 .dac_nids = alc883_dac_nids,
9979 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang189609a2007-08-20 11:31:23 +02009980 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9981 .channel_mode = alc883_3ST_2ch_modes,
9982 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009983 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009984 .setup = alc883_haier_w66_setup,
9985 .init_hook = alc_automute_amp,
Herton Ronaldo Krzesinskieea64192008-03-20 12:14:59 +01009986 },
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009987 [ALC888_3ST_HP] = {
Herton Ronaldo Krzesinskieea64192008-03-20 12:14:59 +01009988 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009989 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009990 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9991 .dac_nids = alc883_dac_nids,
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009992 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
9993 .channel_mode = alc888_3st_hp_modes,
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009994 .need_dac_fix = 1,
9995 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009996 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009997 .setup = alc888_3st_hp_setup,
9998 .init_hook = alc_automute_amp,
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009999 },
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +010010000 [ALC888_6ST_DELL] = {
Herton Ronaldo Krzesinskif24dbdc2008-03-20 12:14:28 +010010001 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +010010002 .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
10003 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10004 .dac_nids = alc883_dac_nids,
10005 .dig_out_nid = ALC883_DIGOUT_NID,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +010010006 .dig_in_nid = ALC883_DIGIN_NID,
10007 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10008 .channel_mode = alc883_sixstack_modes,
10009 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010010 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010011 .setup = alc888_6st_dell_setup,
10012 .init_hook = alc_automute_amp,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +010010013 },
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +010010014 [ALC883_MITAC] = {
10015 .mixers = { alc883_mitac_mixer },
10016 .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
10017 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10018 .dac_nids = alc883_dac_nids,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +010010019 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10020 .channel_mode = alc883_3ST_2ch_modes,
10021 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010022 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010023 .setup = alc883_mitac_setup,
10024 .init_hook = alc_automute_amp,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +010010025 },
Jiang zhefb97dc62008-03-06 11:07:11 +010010026 [ALC883_FUJITSU_PI2515] = {
10027 .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
10028 .init_verbs = { alc883_init_verbs,
10029 alc883_2ch_fujitsu_pi2515_verbs},
10030 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10031 .dac_nids = alc883_dac_nids,
10032 .dig_out_nid = ALC883_DIGOUT_NID,
10033 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10034 .channel_mode = alc883_3ST_2ch_modes,
10035 .input_mux = &alc883_fujitsu_pi2515_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010036 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010037 .setup = alc883_2ch_fujitsu_pi2515_setup,
10038 .init_hook = alc_automute_amp,
Jiang zhefb97dc62008-03-06 11:07:11 +010010039 },
Vincent Petryef8ef5f2008-11-23 11:31:41 +080010040 [ALC888_FUJITSU_XA3530] = {
10041 .mixers = { alc888_base_mixer, alc883_chmode_mixer },
10042 .init_verbs = { alc883_init_verbs,
10043 alc888_fujitsu_xa3530_verbs },
10044 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10045 .dac_nids = alc883_dac_nids,
10046 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10047 .adc_nids = alc883_adc_nids_rev,
10048 .capsrc_nids = alc883_capsrc_nids_rev,
10049 .dig_out_nid = ALC883_DIGOUT_NID,
10050 .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
10051 .channel_mode = alc888_4ST_8ch_intel_modes,
10052 .num_mux_defs =
10053 ARRAY_SIZE(alc888_2_capture_sources),
10054 .input_mux = alc888_2_capture_sources,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010055 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010056 .setup = alc888_fujitsu_xa3530_setup,
10057 .init_hook = alc_automute_amp,
Vincent Petryef8ef5f2008-11-23 11:31:41 +080010058 },
Kailang Yange2757d52008-08-26 13:17:46 +020010059 [ALC888_LENOVO_SKY] = {
10060 .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
10061 .init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
10062 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10063 .dac_nids = alc883_dac_nids,
10064 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yange2757d52008-08-26 13:17:46 +020010065 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10066 .channel_mode = alc883_sixstack_modes,
10067 .need_dac_fix = 1,
10068 .input_mux = &alc883_lenovo_sky_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010069 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010070 .setup = alc888_lenovo_sky_setup,
10071 .init_hook = alc_automute_amp,
Kailang Yange2757d52008-08-26 13:17:46 +020010072 },
10073 [ALC888_ASUS_M90V] = {
10074 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10075 .init_verbs = { alc883_init_verbs, alc888_asus_m90v_verbs },
10076 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10077 .dac_nids = alc883_dac_nids,
10078 .dig_out_nid = ALC883_DIGOUT_NID,
10079 .dig_in_nid = ALC883_DIGIN_NID,
10080 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10081 .channel_mode = alc883_3ST_6ch_modes,
10082 .need_dac_fix = 1,
10083 .input_mux = &alc883_fujitsu_pi2515_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010084 .unsol_event = alc_sku_unsol_event,
10085 .setup = alc883_mode2_setup,
10086 .init_hook = alc_inithook,
Kailang Yange2757d52008-08-26 13:17:46 +020010087 },
10088 [ALC888_ASUS_EEE1601] = {
10089 .mixers = { alc883_asus_eee1601_mixer },
Takashi Iwaif9e336f2008-10-31 16:37:07 +010010090 .cap_mixer = alc883_asus_eee1601_cap_mixer,
Kailang Yange2757d52008-08-26 13:17:46 +020010091 .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
10092 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10093 .dac_nids = alc883_dac_nids,
10094 .dig_out_nid = ALC883_DIGOUT_NID,
10095 .dig_in_nid = ALC883_DIGIN_NID,
10096 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10097 .channel_mode = alc883_3ST_2ch_modes,
10098 .need_dac_fix = 1,
10099 .input_mux = &alc883_asus_eee1601_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010100 .unsol_event = alc_sku_unsol_event,
Kailang Yange2757d52008-08-26 13:17:46 +020010101 .init_hook = alc883_eee1601_inithook,
10102 },
Wu Fengguang3ab90932008-11-17 09:51:09 +010010103 [ALC1200_ASUS_P5Q] = {
10104 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
10105 .init_verbs = { alc883_init_verbs },
10106 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10107 .dac_nids = alc883_dac_nids,
10108 .dig_out_nid = ALC1200_DIGOUT_NID,
10109 .dig_in_nid = ALC883_DIGIN_NID,
Wu Fengguangb25c9da2009-02-06 15:02:27 +080010110 .slave_dig_outs = alc1200_slave_dig_outs,
Wu Fengguang3ab90932008-11-17 09:51:09 +010010111 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10112 .channel_mode = alc883_sixstack_modes,
10113 .input_mux = &alc883_capture_source,
10114 },
Torben Schulzeb4c41d2009-05-18 15:02:35 +020010115 [ALC889A_MB31] = {
10116 .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
10117 .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
10118 alc880_gpio1_init_verbs },
10119 .adc_nids = alc883_adc_nids,
10120 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
Takashi Iwai035eb0c2009-12-17 15:00:26 +010010121 .capsrc_nids = alc883_capsrc_nids,
Torben Schulzeb4c41d2009-05-18 15:02:35 +020010122 .dac_nids = alc883_dac_nids,
10123 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10124 .channel_mode = alc889A_mb31_6ch_modes,
10125 .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
10126 .input_mux = &alc889A_mb31_capture_source,
10127 .dig_out_nid = ALC883_DIGOUT_NID,
10128 .unsol_event = alc889A_mb31_unsol_event,
10129 .init_hook = alc889A_mb31_automute,
10130 },
Guido Günther3e1647c2009-06-05 00:47:26 +020010131 [ALC883_SONY_VAIO_TT] = {
10132 .mixers = { alc883_vaiott_mixer },
10133 .init_verbs = { alc883_init_verbs, alc883_vaiott_verbs },
10134 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10135 .dac_nids = alc883_dac_nids,
10136 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10137 .channel_mode = alc883_3ST_2ch_modes,
10138 .input_mux = &alc883_capture_source,
10139 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010140 .setup = alc883_vaiott_setup,
10141 .init_hook = alc_automute_amp,
Guido Günther3e1647c2009-06-05 00:47:26 +020010142 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010143};
10144
10145
10146/*
Takashi Iwai4953550a2009-06-30 15:28:30 +020010147 * Pin config fixes
10148 */
10149enum {
10150 PINFIX_ABIT_AW9D_MAX
10151};
10152
10153static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
10154 { 0x15, 0x01080104 }, /* side */
10155 { 0x16, 0x01011012 }, /* rear */
10156 { 0x17, 0x01016011 }, /* clfe */
10157 { }
10158};
10159
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010160static const struct alc_fixup alc882_fixups[] = {
10161 [PINFIX_ABIT_AW9D_MAX] = {
10162 .pins = alc882_abit_aw9d_pinfix
10163 },
Takashi Iwai4953550a2009-06-30 15:28:30 +020010164};
10165
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010166static struct snd_pci_quirk alc882_fixup_tbl[] = {
Takashi Iwai4953550a2009-06-30 15:28:30 +020010167 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
10168 {}
10169};
10170
10171/*
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010172 * BIOS auto configuration
10173 */
Takashi Iwai05f5f472009-08-25 13:10:18 +020010174static int alc882_auto_create_input_ctls(struct hda_codec *codec,
10175 const struct auto_pin_cfg *cfg)
10176{
10177 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x23, 0x22);
10178}
10179
Takashi Iwai4953550a2009-06-30 15:28:30 +020010180static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010181 hda_nid_t nid, int pin_type,
10182 int dac_idx)
10183{
10184 /* set as output */
10185 struct alc_spec *spec = codec->spec;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010186 int idx;
10187
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010188 alc_set_pin_output(codec, nid, pin_type);
Takashi Iwaif9700d52010-04-05 23:25:13 +020010189 if (dac_idx >= spec->multiout.num_dacs)
10190 return;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010191 if (spec->multiout.dac_nids[dac_idx] == 0x25)
10192 idx = 4;
Takashi Iwaif9700d52010-04-05 23:25:13 +020010193 else
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010194 idx = spec->multiout.dac_nids[dac_idx] - 2;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010195 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
10196
10197}
10198
Takashi Iwai4953550a2009-06-30 15:28:30 +020010199static void alc882_auto_init_multi_out(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010200{
10201 struct alc_spec *spec = codec->spec;
10202 int i;
10203
10204 for (i = 0; i <= HDA_SIDE; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010205 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020010206 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010207 if (nid)
Takashi Iwai4953550a2009-06-30 15:28:30 +020010208 alc882_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010209 i);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010210 }
10211}
10212
Takashi Iwai4953550a2009-06-30 15:28:30 +020010213static void alc882_auto_init_hp_out(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010214{
10215 struct alc_spec *spec = codec->spec;
10216 hda_nid_t pin;
10217
Takashi Iwaieb06ed82006-09-20 17:10:27 +020010218 pin = spec->autocfg.hp_pins[0];
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010219 if (pin) /* connect to front */
10220 /* use dac 0 */
Takashi Iwai4953550a2009-06-30 15:28:30 +020010221 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010222 pin = spec->autocfg.speaker_pins[0];
10223 if (pin)
Takashi Iwai4953550a2009-06-30 15:28:30 +020010224 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010225}
10226
Takashi Iwai4953550a2009-06-30 15:28:30 +020010227static void alc882_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010228{
10229 struct alc_spec *spec = codec->spec;
10230 int i;
10231
10232 for (i = 0; i < AUTO_PIN_LAST; i++) {
10233 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai4953550a2009-06-30 15:28:30 +020010234 if (!nid)
10235 continue;
Takashi Iwai0d971c92009-06-30 16:11:11 +020010236 alc_set_input_pin(codec, nid, i);
Takashi Iwai4953550a2009-06-30 15:28:30 +020010237 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
10238 snd_hda_codec_write(codec, nid, 0,
10239 AC_VERB_SET_AMP_GAIN_MUTE,
10240 AMP_OUT_MUTE);
10241 }
10242}
10243
10244static void alc882_auto_init_input_src(struct hda_codec *codec)
10245{
10246 struct alc_spec *spec = codec->spec;
10247 int c;
10248
10249 for (c = 0; c < spec->num_adc_nids; c++) {
10250 hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
10251 hda_nid_t nid = spec->capsrc_nids[c];
10252 unsigned int mux_idx;
10253 const struct hda_input_mux *imux;
10254 int conns, mute, idx, item;
10255
10256 conns = snd_hda_get_connections(codec, nid, conn_list,
10257 ARRAY_SIZE(conn_list));
10258 if (conns < 0)
10259 continue;
10260 mux_idx = c >= spec->num_mux_defs ? 0 : c;
10261 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +010010262 if (!imux->num_items && mux_idx > 0)
10263 imux = &spec->input_mux[0];
Takashi Iwai4953550a2009-06-30 15:28:30 +020010264 for (idx = 0; idx < conns; idx++) {
10265 /* if the current connection is the selected one,
10266 * unmute it as default - otherwise mute it
10267 */
10268 mute = AMP_IN_MUTE(idx);
10269 for (item = 0; item < imux->num_items; item++) {
10270 if (imux->items[item].index == idx) {
10271 if (spec->cur_mux[c] == item)
10272 mute = AMP_IN_UNMUTE(idx);
10273 break;
10274 }
10275 }
10276 /* check if we have a selector or mixer
10277 * we could check for the widget type instead, but
10278 * just check for Amp-In presence (in case of mixer
10279 * without amp-in there is something wrong, this
10280 * function shouldn't be used or capsrc nid is wrong)
10281 */
10282 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010283 snd_hda_codec_write(codec, nid, 0,
10284 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwai4953550a2009-06-30 15:28:30 +020010285 mute);
10286 else if (mute != AMP_IN_MUTE(idx))
10287 snd_hda_codec_write(codec, nid, 0,
10288 AC_VERB_SET_CONNECT_SEL,
10289 idx);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010290 }
10291 }
10292}
10293
Takashi Iwai4953550a2009-06-30 15:28:30 +020010294/* add mic boosts if needed */
10295static int alc_auto_add_mic_boost(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010296{
10297 struct alc_spec *spec = codec->spec;
Takashi Iwai4953550a2009-06-30 15:28:30 +020010298 int err;
10299 hda_nid_t nid;
10300
10301 nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
10302 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
10303 err = add_control(spec, ALC_CTL_WIDGET_VOL,
10304 "Mic Boost",
10305 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
10306 if (err < 0)
10307 return err;
10308 }
10309 nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
10310 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
10311 err = add_control(spec, ALC_CTL_WIDGET_VOL,
10312 "Front Mic Boost",
10313 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
10314 if (err < 0)
10315 return err;
10316 }
10317 return 0;
10318}
10319
10320/* almost identical with ALC880 parser... */
10321static int alc882_parse_auto_config(struct hda_codec *codec)
10322{
10323 struct alc_spec *spec = codec->spec;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010324 static hda_nid_t alc882_ignore[] = { 0x1d, 0 };
10325 int i, err;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010326
Takashi Iwai05f5f472009-08-25 13:10:18 +020010327 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
10328 alc882_ignore);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010329 if (err < 0)
10330 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010331 if (!spec->autocfg.line_outs)
10332 return 0; /* can't find valid BIOS pin config */
10333
10334 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
10335 if (err < 0)
10336 return err;
10337 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
10338 if (err < 0)
10339 return err;
10340 err = alc880_auto_create_extra_out(spec,
10341 spec->autocfg.speaker_pins[0],
10342 "Speaker");
10343 if (err < 0)
10344 return err;
10345 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
10346 "Headphone");
10347 if (err < 0)
10348 return err;
10349 err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
10350 if (err < 0)
10351 return err;
10352
10353 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
10354
10355 /* check multiple SPDIF-out (for recent codecs) */
10356 for (i = 0; i < spec->autocfg.dig_outs; i++) {
10357 hda_nid_t dig_nid;
10358 err = snd_hda_get_connections(codec,
10359 spec->autocfg.dig_out_pins[i],
10360 &dig_nid, 1);
10361 if (err < 0)
10362 continue;
10363 if (!i)
10364 spec->multiout.dig_out_nid = dig_nid;
10365 else {
10366 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
Roel Kluin71121d9f2009-11-10 20:11:55 +010010367 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
Takashi Iwai05f5f472009-08-25 13:10:18 +020010368 break;
Roel Kluin71121d9f2009-11-10 20:11:55 +010010369 spec->slave_dig_outs[i - 1] = dig_nid;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010370 }
10371 }
10372 if (spec->autocfg.dig_in_pin)
10373 spec->dig_in_nid = ALC880_DIGIN_NID;
10374
10375 if (spec->kctls.list)
10376 add_mixer(spec, spec->kctls.list);
10377
10378 add_verb(spec, alc883_auto_init_verbs);
10379 /* if ADC 0x07 is available, initialize it, too */
10380 if (get_wcaps_type(get_wcaps(codec, 0x07)) == AC_WID_AUD_IN)
10381 add_verb(spec, alc882_adc1_init_verbs);
10382
10383 spec->num_mux_defs = 1;
10384 spec->input_mux = &spec->private_imux[0];
10385
Kailang Yang6227cdc2010-02-25 08:36:52 +010010386 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai776e1842007-08-29 15:07:11 +020010387
10388 err = alc_auto_add_mic_boost(codec);
10389 if (err < 0)
10390 return err;
10391
Takashi Iwai776e1842007-08-29 15:07:11 +020010392 return 1; /* config found */
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010393}
10394
10395/* additional initialization for auto-configuration model */
Takashi Iwai4953550a2009-06-30 15:28:30 +020010396static void alc882_auto_init(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010397{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010398 struct alc_spec *spec = codec->spec;
Takashi Iwai4953550a2009-06-30 15:28:30 +020010399 alc882_auto_init_multi_out(codec);
10400 alc882_auto_init_hp_out(codec);
10401 alc882_auto_init_analog_input(codec);
10402 alc882_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010403 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020010404 alc_inithook(codec);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010405}
10406
Takashi Iwai4953550a2009-06-30 15:28:30 +020010407static int patch_alc882(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010408{
10409 struct alc_spec *spec;
10410 int err, board_config;
10411
10412 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
10413 if (spec == NULL)
10414 return -ENOMEM;
10415
10416 codec->spec = spec;
10417
Takashi Iwai4953550a2009-06-30 15:28:30 +020010418 switch (codec->vendor_id) {
10419 case 0x10ec0882:
10420 case 0x10ec0885:
10421 break;
10422 default:
10423 /* ALC883 and variants */
10424 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
10425 break;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010426 }
10427
Takashi Iwai4953550a2009-06-30 15:28:30 +020010428 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
10429 alc882_models,
10430 alc882_cfg_tbl);
10431
10432 if (board_config < 0 || board_config >= ALC882_MODEL_LAST)
10433 board_config = snd_hda_check_board_codec_sid_config(codec,
10434 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
10435
10436 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020010437 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
Takashi Iwai4953550a2009-06-30 15:28:30 +020010438 codec->chip_name);
10439 board_config = ALC882_AUTO;
10440 }
10441
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010442 alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups);
Takashi Iwai4953550a2009-06-30 15:28:30 +020010443
10444 if (board_config == ALC882_AUTO) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010445 /* automatic parse from the BIOS config */
Takashi Iwai4953550a2009-06-30 15:28:30 +020010446 err = alc882_parse_auto_config(codec);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010447 if (err < 0) {
10448 alc_free(codec);
10449 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010450 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010451 printk(KERN_INFO
10452 "hda_codec: Cannot set up configuration "
10453 "from BIOS. Using base mode...\n");
Takashi Iwai4953550a2009-06-30 15:28:30 +020010454 board_config = ALC882_3ST_DIG;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010455 }
10456 }
10457
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090010458 err = snd_hda_attach_beep_device(codec, 0x1);
10459 if (err < 0) {
10460 alc_free(codec);
10461 return err;
10462 }
10463
Takashi Iwai4953550a2009-06-30 15:28:30 +020010464 if (board_config != ALC882_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020010465 setup_preset(codec, &alc882_presets[board_config]);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010466
Takashi Iwai4953550a2009-06-30 15:28:30 +020010467 spec->stream_analog_playback = &alc882_pcm_analog_playback;
10468 spec->stream_analog_capture = &alc882_pcm_analog_capture;
10469 /* FIXME: setup DAC5 */
10470 /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
10471 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
10472
10473 spec->stream_digital_playback = &alc882_pcm_digital_playback;
10474 spec->stream_digital_capture = &alc882_pcm_digital_capture;
10475
10476 if (codec->vendor_id == 0x10ec0888)
Takashi Iwai4a79ba32009-04-22 16:31:35 +020010477 spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */
Takashi Iwai4953550a2009-06-30 15:28:30 +020010478
10479 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010480 int i, j;
Takashi Iwai4953550a2009-06-30 15:28:30 +020010481 spec->num_adc_nids = 0;
10482 for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010483 const struct hda_input_mux *imux = spec->input_mux;
Takashi Iwai4953550a2009-06-30 15:28:30 +020010484 hda_nid_t cap;
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010485 hda_nid_t items[16];
Takashi Iwai4953550a2009-06-30 15:28:30 +020010486 hda_nid_t nid = alc882_adc_nids[i];
10487 unsigned int wcap = get_wcaps(codec, nid);
10488 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020010489 wcap = get_wcaps_type(wcap);
Takashi Iwai4953550a2009-06-30 15:28:30 +020010490 if (wcap != AC_WID_AUD_IN)
10491 continue;
10492 spec->private_adc_nids[spec->num_adc_nids] = nid;
10493 err = snd_hda_get_connections(codec, nid, &cap, 1);
10494 if (err < 0)
10495 continue;
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010496 err = snd_hda_get_connections(codec, cap, items,
10497 ARRAY_SIZE(items));
10498 if (err < 0)
10499 continue;
10500 for (j = 0; j < imux->num_items; j++)
10501 if (imux->items[j].index >= err)
10502 break;
10503 if (j < imux->num_items)
10504 continue;
Takashi Iwai4953550a2009-06-30 15:28:30 +020010505 spec->private_capsrc_nids[spec->num_adc_nids] = cap;
10506 spec->num_adc_nids++;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020010507 }
Takashi Iwai4953550a2009-06-30 15:28:30 +020010508 spec->adc_nids = spec->private_adc_nids;
10509 spec->capsrc_nids = spec->private_capsrc_nids;
Kailang Yang2f893282008-05-27 12:14:47 +020010510 }
10511
Takashi Iwaib59bdf32009-08-11 09:47:30 +020010512 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010010513 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010514
Takashi Iwai2134ea42008-01-10 16:53:55 +010010515 spec->vmaster_nid = 0x0c;
10516
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010517 codec->patch_ops = alc_patch_ops;
Takashi Iwai4953550a2009-06-30 15:28:30 +020010518 if (board_config == ALC882_AUTO)
10519 spec->init_hook = alc882_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020010520#ifdef CONFIG_SND_HDA_POWER_SAVE
10521 if (!spec->loopback.amplist)
Takashi Iwai4953550a2009-06-30 15:28:30 +020010522 spec->loopback.amplist = alc882_loopbacks;
Takashi Iwaicb53c622007-08-10 17:21:45 +020010523#endif
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010524
10525 return 0;
10526}
10527
Takashi Iwai4953550a2009-06-30 15:28:30 +020010528
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010529/*
Kailang Yangdf694da2005-12-05 19:42:22 +010010530 * ALC262 support
10531 */
10532
10533#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
10534#define ALC262_DIGIN_NID ALC880_DIGIN_NID
10535
10536#define alc262_dac_nids alc260_dac_nids
10537#define alc262_adc_nids alc882_adc_nids
10538#define alc262_adc_nids_alt alc882_adc_nids_alt
Takashi Iwai88c71a92008-02-14 17:27:17 +010010539#define alc262_capsrc_nids alc882_capsrc_nids
10540#define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
Kailang Yangdf694da2005-12-05 19:42:22 +010010541
10542#define alc262_modes alc260_modes
Takashi Iwaic5f2ea02005-12-06 18:54:31 +010010543#define alc262_capture_source alc882_capture_source
Kailang Yangdf694da2005-12-05 19:42:22 +010010544
Kailang Yang4e555fe2008-08-26 13:05:55 +020010545static hda_nid_t alc262_dmic_adc_nids[1] = {
10546 /* ADC0 */
10547 0x09
10548};
10549
10550static hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
10551
Kailang Yangdf694da2005-12-05 19:42:22 +010010552static struct snd_kcontrol_new alc262_base_mixer[] = {
10553 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10554 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
10555 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10556 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10557 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10558 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10559 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10560 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010561 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010562 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10563 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010564 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010565 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
10566 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10567 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
10568 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010569 { } /* end */
Takashi Iwai834be882006-03-01 14:16:17 +010010570};
10571
Takashi Iwaice875f02008-01-28 18:17:43 +010010572/* update HP, line and mono-out pins according to the master switch */
10573static void alc262_hp_master_update(struct hda_codec *codec)
10574{
10575 struct alc_spec *spec = codec->spec;
10576 int val = spec->master_sw;
10577
10578 /* HP & line-out */
10579 snd_hda_codec_write_cache(codec, 0x1b, 0,
10580 AC_VERB_SET_PIN_WIDGET_CONTROL,
10581 val ? PIN_HP : 0);
10582 snd_hda_codec_write_cache(codec, 0x15, 0,
10583 AC_VERB_SET_PIN_WIDGET_CONTROL,
10584 val ? PIN_HP : 0);
10585 /* mono (speaker) depending on the HP jack sense */
10586 val = val && !spec->jack_present;
10587 snd_hda_codec_write_cache(codec, 0x16, 0,
10588 AC_VERB_SET_PIN_WIDGET_CONTROL,
10589 val ? PIN_OUT : 0);
10590}
10591
10592static void alc262_hp_bpc_automute(struct hda_codec *codec)
10593{
10594 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +080010595
10596 spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
Takashi Iwaice875f02008-01-28 18:17:43 +010010597 alc262_hp_master_update(codec);
10598}
10599
10600static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)
10601{
10602 if ((res >> 26) != ALC880_HP_EVENT)
10603 return;
10604 alc262_hp_bpc_automute(codec);
10605}
10606
10607static void alc262_hp_wildwest_automute(struct hda_codec *codec)
10608{
10609 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +080010610
10611 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwaice875f02008-01-28 18:17:43 +010010612 alc262_hp_master_update(codec);
10613}
10614
10615static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,
10616 unsigned int res)
10617{
10618 if ((res >> 26) != ALC880_HP_EVENT)
10619 return;
10620 alc262_hp_wildwest_automute(codec);
10621}
10622
Takashi Iwaib72519b2009-05-08 14:31:55 +020010623#define alc262_hp_master_sw_get alc260_hp_master_sw_get
Takashi Iwaice875f02008-01-28 18:17:43 +010010624
10625static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
10626 struct snd_ctl_elem_value *ucontrol)
10627{
10628 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10629 struct alc_spec *spec = codec->spec;
10630 int val = !!*ucontrol->value.integer.value;
10631
10632 if (val == spec->master_sw)
10633 return 0;
10634 spec->master_sw = val;
10635 alc262_hp_master_update(codec);
10636 return 1;
10637}
10638
Takashi Iwaib72519b2009-05-08 14:31:55 +020010639#define ALC262_HP_MASTER_SWITCH \
10640 { \
10641 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
10642 .name = "Master Playback Switch", \
10643 .info = snd_ctl_boolean_mono_info, \
10644 .get = alc262_hp_master_sw_get, \
10645 .put = alc262_hp_master_sw_put, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010010646 }, \
10647 { \
10648 .iface = NID_MAPPING, \
10649 .name = "Master Playback Switch", \
10650 .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \
Takashi Iwaib72519b2009-05-08 14:31:55 +020010651 }
10652
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010010653
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010654static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
Takashi Iwaib72519b2009-05-08 14:31:55 +020010655 ALC262_HP_MASTER_SWITCH,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010656 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10657 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10658 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Takashi Iwaice875f02008-01-28 18:17:43 +010010659 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
10660 HDA_OUTPUT),
10661 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
10662 HDA_OUTPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010663 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10664 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010665 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010666 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10667 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010668 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010669 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10670 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10671 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10672 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010673 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
10674 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
10675 { } /* end */
10676};
10677
Kailang Yangcd7509a2007-01-26 18:33:17 +010010678static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
Takashi Iwaib72519b2009-05-08 14:31:55 +020010679 ALC262_HP_MASTER_SWITCH,
Kailang Yangcd7509a2007-01-26 18:33:17 +010010680 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10681 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10682 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
10683 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwaice875f02008-01-28 18:17:43 +010010684 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
10685 HDA_OUTPUT),
10686 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
10687 HDA_OUTPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010688 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
10689 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010690 HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010691 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
10692 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
10693 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10694 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010695 { } /* end */
10696};
10697
10698static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
10699 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10700 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010701 HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010702 { } /* end */
10703};
10704
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010705/* mute/unmute internal speaker according to the hp jack and mute state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010706static void alc262_hp_t5735_setup(struct hda_codec *codec)
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010707{
10708 struct alc_spec *spec = codec->spec;
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010709
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010710 spec->autocfg.hp_pins[0] = 0x15;
Takashi Iwaidc99be42010-01-20 08:35:06 +010010711 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010712}
10713
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010714static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
Takashi Iwai86cd9292008-01-28 18:09:56 +010010715 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10716 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010717 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
10718 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10719 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10720 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10721 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10722 { } /* end */
10723};
10724
10725static struct hda_verb alc262_hp_t5735_verbs[] = {
10726 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10727 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10728
10729 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
10730 { }
10731};
10732
Kailang Yang8c427222008-01-10 13:03:59 +010010733static struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
Takashi Iwaif2f48e12008-01-28 18:14:43 +010010734 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10735 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +010010736 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
10737 HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010010738 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
10739 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
10740 { } /* end */
10741};
10742
10743static struct hda_verb alc262_hp_rp5700_verbs[] = {
10744 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10745 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10746 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10747 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10748 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10749 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
10750 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
10751 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
10752 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
10753 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
10754 {}
10755};
10756
10757static struct hda_input_mux alc262_hp_rp5700_capture_source = {
10758 .num_items = 1,
10759 .items = {
10760 { "Line", 0x1 },
10761 },
10762};
10763
Takashi Iwai42171c12009-05-08 14:11:43 +020010764/* bind hp and internal speaker mute (with plug check) as master switch */
10765static void alc262_hippo_master_update(struct hda_codec *codec)
10766{
10767 struct alc_spec *spec = codec->spec;
10768 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
10769 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
10770 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
10771 unsigned int mute;
10772
10773 /* HP */
10774 mute = spec->master_sw ? 0 : HDA_AMP_MUTE;
10775 snd_hda_codec_amp_stereo(codec, hp_nid, HDA_OUTPUT, 0,
10776 HDA_AMP_MUTE, mute);
10777 /* mute internal speaker per jack sense */
10778 if (spec->jack_present)
10779 mute = HDA_AMP_MUTE;
10780 if (line_nid)
10781 snd_hda_codec_amp_stereo(codec, line_nid, HDA_OUTPUT, 0,
10782 HDA_AMP_MUTE, mute);
10783 if (speaker_nid && speaker_nid != line_nid)
10784 snd_hda_codec_amp_stereo(codec, speaker_nid, HDA_OUTPUT, 0,
10785 HDA_AMP_MUTE, mute);
10786}
10787
10788#define alc262_hippo_master_sw_get alc262_hp_master_sw_get
10789
10790static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
10791 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai0724ea22007-08-23 00:31:43 +020010792{
10793 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
Takashi Iwai42171c12009-05-08 14:11:43 +020010794 struct alc_spec *spec = codec->spec;
10795 int val = !!*ucontrol->value.integer.value;
Takashi Iwai0724ea22007-08-23 00:31:43 +020010796
Takashi Iwai42171c12009-05-08 14:11:43 +020010797 if (val == spec->master_sw)
10798 return 0;
10799 spec->master_sw = val;
10800 alc262_hippo_master_update(codec);
10801 return 1;
Takashi Iwai0724ea22007-08-23 00:31:43 +020010802}
Takashi Iwai5b319542007-07-26 11:49:22 +020010803
Takashi Iwai42171c12009-05-08 14:11:43 +020010804#define ALC262_HIPPO_MASTER_SWITCH \
10805 { \
10806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
10807 .name = "Master Playback Switch", \
10808 .info = snd_ctl_boolean_mono_info, \
10809 .get = alc262_hippo_master_sw_get, \
10810 .put = alc262_hippo_master_sw_put, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010010811 }, \
10812 { \
10813 .iface = NID_MAPPING, \
10814 .name = "Master Playback Switch", \
10815 .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
10816 (SUBDEV_SPEAKER(0) << 16), \
Takashi Iwai42171c12009-05-08 14:11:43 +020010817 }
10818
10819static struct snd_kcontrol_new alc262_hippo_mixer[] = {
10820 ALC262_HIPPO_MASTER_SWITCH,
10821 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10822 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10823 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10824 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10825 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10826 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10827 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10828 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10829 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10830 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10831 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
10832 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
10833 { } /* end */
10834};
10835
10836static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
10837 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10838 ALC262_HIPPO_MASTER_SWITCH,
10839 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10840 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10841 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10842 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10843 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10844 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10845 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10846 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10847 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10848 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
10849 { } /* end */
10850};
10851
10852/* mute/unmute internal speaker according to the hp jack and mute state */
10853static void alc262_hippo_automute(struct hda_codec *codec)
10854{
10855 struct alc_spec *spec = codec->spec;
10856 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai42171c12009-05-08 14:11:43 +020010857
Wu Fengguang864f92b2009-11-18 12:38:02 +080010858 spec->jack_present = snd_hda_jack_detect(codec, hp_nid);
Takashi Iwai42171c12009-05-08 14:11:43 +020010859 alc262_hippo_master_update(codec);
10860}
10861
10862static void alc262_hippo_unsol_event(struct hda_codec *codec, unsigned int res)
10863{
10864 if ((res >> 26) != ALC880_HP_EVENT)
10865 return;
10866 alc262_hippo_automute(codec);
10867}
10868
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010869static void alc262_hippo_setup(struct hda_codec *codec)
Takashi Iwai42171c12009-05-08 14:11:43 +020010870{
10871 struct alc_spec *spec = codec->spec;
10872
10873 spec->autocfg.hp_pins[0] = 0x15;
10874 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai42171c12009-05-08 14:11:43 +020010875}
10876
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010877static void alc262_hippo1_setup(struct hda_codec *codec)
Takashi Iwai42171c12009-05-08 14:11:43 +020010878{
10879 struct alc_spec *spec = codec->spec;
10880
10881 spec->autocfg.hp_pins[0] = 0x1b;
10882 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai42171c12009-05-08 14:11:43 +020010883}
10884
10885
Kailang Yang272a5272007-05-14 11:00:38 +020010886static struct snd_kcontrol_new alc262_sony_mixer[] = {
Takashi Iwai0724ea22007-08-23 00:31:43 +020010887 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai42171c12009-05-08 14:11:43 +020010888 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang272a5272007-05-14 11:00:38 +020010889 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10890 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10891 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10892 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10893 { } /* end */
10894};
10895
Kailang Yang83c34212007-07-05 11:43:05 +020010896static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020010897 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10898 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang83c34212007-07-05 11:43:05 +020010899 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10900 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10901 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10902 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10903 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10904 { } /* end */
10905};
Kailang Yang272a5272007-05-14 11:00:38 +020010906
Tony Vroonba340e82009-02-02 19:01:30 +000010907static struct snd_kcontrol_new alc262_tyan_mixer[] = {
10908 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10909 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
10910 HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
10911 HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
10912 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10913 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10914 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10915 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10916 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10917 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10918 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10919 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
10920 { } /* end */
10921};
10922
10923static struct hda_verb alc262_tyan_verbs[] = {
10924 /* Headphone automute */
10925 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
10926 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10927 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
10928
10929 /* P11 AUX_IN, white 4-pin connector */
10930 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10931 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
10932 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
10933 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
10934
10935 {}
10936};
10937
10938/* unsolicited event for HP jack sensing */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010939static void alc262_tyan_setup(struct hda_codec *codec)
Tony Vroonba340e82009-02-02 19:01:30 +000010940{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010941 struct alc_spec *spec = codec->spec;
Tony Vroonba340e82009-02-02 19:01:30 +000010942
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010943 spec->autocfg.hp_pins[0] = 0x1b;
10944 spec->autocfg.speaker_pins[0] = 0x15;
Tony Vroonba340e82009-02-02 19:01:30 +000010945}
10946
Tony Vroonba340e82009-02-02 19:01:30 +000010947
Kailang Yangdf694da2005-12-05 19:42:22 +010010948#define alc262_capture_mixer alc882_capture_mixer
10949#define alc262_capture_alt_mixer alc882_capture_alt_mixer
10950
10951/*
10952 * generic initialization of ADC, input mixers and output mixers
10953 */
10954static struct hda_verb alc262_init_verbs[] = {
10955 /*
10956 * Unmute ADC0-2 and set the default input to mic-in
10957 */
10958 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
10959 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10960 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
10961 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10962 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
10963 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10964
Takashi Iwaicb53c622007-08-10 17:21:45 +020010965 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangdf694da2005-12-05 19:42:22 +010010966 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010967 * Note: PASD motherboards uses the Line In 2 as the input for
10968 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +010010969 */
10970 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020010971 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
10972 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
10973 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
10974 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
10975 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +010010976
10977 /*
10978 * Set up output mixers (0x0c - 0x0e)
10979 */
10980 /* set vol=0 to output mixers */
10981 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10982 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10983 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10984 /* set up input amps for analog loopback */
10985 /* Amp Indices: DAC = 0, mixer = 1 */
10986 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10987 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10988 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10989 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10990 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10991 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10992
10993 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
10994 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
10995 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
10996 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
10997 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10998 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10999
11000 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11001 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11002 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11003 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11004 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Kailang Yangea1fb292008-08-26 12:58:38 +020011005
Kailang Yangdf694da2005-12-05 19:42:22 +010011006 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
11007 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
Kailang Yangea1fb292008-08-26 12:58:38 +020011008
Kailang Yangdf694da2005-12-05 19:42:22 +010011009 /* FIXME: use matrix-type input source selection */
11010 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11011 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11012 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11013 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11014 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11015 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11016 /* Input mixer2 */
11017 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11018 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11019 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11020 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11021 /* Input mixer3 */
11022 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11023 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11024 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011025 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
Kailang Yangdf694da2005-12-05 19:42:22 +010011026
11027 { }
11028};
11029
Kailang Yang4e555fe2008-08-26 13:05:55 +020011030static struct hda_verb alc262_eapd_verbs[] = {
11031 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
11032 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
11033 { }
11034};
11035
Kailang Yangccc656c2006-10-17 12:32:26 +020011036static struct hda_verb alc262_hippo1_unsol_verbs[] = {
11037 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11038 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11039 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11040
11041 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11042 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11043 {}
11044};
11045
Kailang Yang272a5272007-05-14 11:00:38 +020011046static struct hda_verb alc262_sony_unsol_verbs[] = {
11047 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11048 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11049 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
11050
11051 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11052 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Akio Idehara7b1e8792008-06-09 22:46:07 +090011053 {}
Kailang Yang272a5272007-05-14 11:00:38 +020011054};
11055
Kailang Yang4e555fe2008-08-26 13:05:55 +020011056static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
11057 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11058 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11059 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11060 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11061 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yang4e555fe2008-08-26 13:05:55 +020011062 { } /* end */
11063};
11064
11065static struct hda_verb alc262_toshiba_s06_verbs[] = {
11066 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11067 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11068 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11069 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11070 {0x22, AC_VERB_SET_CONNECT_SEL, 0x09},
11071 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11072 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
11073 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11074 {}
11075};
11076
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011077static void alc262_toshiba_s06_setup(struct hda_codec *codec)
Kailang Yang4e555fe2008-08-26 13:05:55 +020011078{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020011079 struct alc_spec *spec = codec->spec;
11080
11081 spec->autocfg.hp_pins[0] = 0x15;
11082 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011083 spec->ext_mic.pin = 0x18;
11084 spec->ext_mic.mux_idx = 0;
11085 spec->int_mic.pin = 0x12;
11086 spec->int_mic.mux_idx = 9;
11087 spec->auto_mic = 1;
Kailang Yang4e555fe2008-08-26 13:05:55 +020011088}
11089
Takashi Iwai834be882006-03-01 14:16:17 +010011090/*
Pascal Terjane8f9ae22008-08-04 14:36:05 +020011091 * nec model
11092 * 0x15 = headphone
11093 * 0x16 = internal speaker
11094 * 0x18 = external mic
11095 */
11096
11097static struct snd_kcontrol_new alc262_nec_mixer[] = {
11098 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
11099 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
11100
11101 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11102 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11103 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11104
11105 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11106 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11107 { } /* end */
11108};
11109
11110static struct hda_verb alc262_nec_verbs[] = {
11111 /* Unmute Speaker */
11112 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11113
11114 /* Headphone */
11115 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11116 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11117
11118 /* External mic to headphone */
11119 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11120 /* External mic to speaker */
11121 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11122 {}
11123};
11124
11125/*
Takashi Iwai834be882006-03-01 14:16:17 +010011126 * fujitsu model
Tony Vroon5d9fab22008-03-14 17:09:18 +010011127 * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
11128 * 0x1b = port replicator headphone out
Takashi Iwai834be882006-03-01 14:16:17 +010011129 */
11130
11131#define ALC_HP_EVENT 0x37
11132
11133static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
11134 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11135 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Tony Vroon5d9fab22008-03-14 17:09:18 +010011136 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11137 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai834be882006-03-01 14:16:17 +010011138 {}
11139};
11140
Jiang zhe0e31daf2008-03-20 12:12:39 +010011141static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
11142 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11143 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11144 {}
11145};
11146
Daniel T Chene2595322009-12-19 18:19:02 -050011147static struct hda_verb alc262_lenovo_3000_init_verbs[] = {
11148 /* Front Mic pin: input vref at 50% */
11149 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
11150 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11151 {}
11152};
11153
Takashi Iwai834be882006-03-01 14:16:17 +010011154static struct hda_input_mux alc262_fujitsu_capture_source = {
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011155 .num_items = 3,
Takashi Iwai834be882006-03-01 14:16:17 +010011156 .items = {
11157 { "Mic", 0x0 },
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011158 { "Int Mic", 0x1 },
Takashi Iwai834be882006-03-01 14:16:17 +010011159 { "CD", 0x4 },
11160 },
11161};
11162
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011163static struct hda_input_mux alc262_HP_capture_source = {
11164 .num_items = 5,
11165 .items = {
11166 { "Mic", 0x0 },
zhejiangaccbe492007-08-31 12:36:05 +020011167 { "Front Mic", 0x1 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011168 { "Line", 0x2 },
11169 { "CD", 0x4 },
11170 { "AUX IN", 0x6 },
11171 },
11172};
11173
zhejiangaccbe492007-08-31 12:36:05 +020011174static struct hda_input_mux alc262_HP_D7000_capture_source = {
11175 .num_items = 4,
11176 .items = {
11177 { "Mic", 0x0 },
11178 { "Front Mic", 0x2 },
11179 { "Line", 0x1 },
11180 { "CD", 0x4 },
11181 },
11182};
11183
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011184/* mute/unmute internal speaker according to the hp jacks and mute state */
Takashi Iwai834be882006-03-01 14:16:17 +010011185static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
11186{
11187 struct alc_spec *spec = codec->spec;
11188 unsigned int mute;
11189
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011190 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011191 spec->jack_present = snd_hda_jack_detect(codec, 0x14) ||
11192 snd_hda_jack_detect(codec, 0x1b);
Takashi Iwai834be882006-03-01 14:16:17 +010011193 spec->sense_updated = 1;
11194 }
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011195 /* unmute internal speaker only if both HPs are unplugged and
11196 * master switch is on
11197 */
11198 if (spec->jack_present)
11199 mute = HDA_AMP_MUTE;
11200 else
Takashi Iwai834be882006-03-01 14:16:17 +010011201 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011202 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
11203 HDA_AMP_MUTE, mute);
Takashi Iwai834be882006-03-01 14:16:17 +010011204}
11205
11206/* unsolicited event for HP jack sensing */
11207static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
11208 unsigned int res)
11209{
11210 if ((res >> 26) != ALC_HP_EVENT)
11211 return;
11212 alc262_fujitsu_automute(codec, 1);
11213}
11214
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011215static void alc262_fujitsu_init_hook(struct hda_codec *codec)
11216{
11217 alc262_fujitsu_automute(codec, 1);
11218}
11219
Takashi Iwai834be882006-03-01 14:16:17 +010011220/* bind volumes of both NID 0x0c and 0x0d */
Takashi Iwaicca3b372007-08-10 17:12:15 +020011221static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
11222 .ops = &snd_hda_bind_vol,
11223 .values = {
11224 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
11225 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
11226 0
11227 },
11228};
Takashi Iwai834be882006-03-01 14:16:17 +010011229
Jiang zhe0e31daf2008-03-20 12:12:39 +010011230/* mute/unmute internal speaker according to the hp jack and mute state */
11231static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
11232{
11233 struct alc_spec *spec = codec->spec;
11234 unsigned int mute;
11235
11236 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011237 spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
Jiang zhe0e31daf2008-03-20 12:12:39 +010011238 spec->sense_updated = 1;
11239 }
11240 if (spec->jack_present) {
11241 /* mute internal speaker */
11242 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11243 HDA_AMP_MUTE, HDA_AMP_MUTE);
11244 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
11245 HDA_AMP_MUTE, HDA_AMP_MUTE);
11246 } else {
11247 /* unmute internal speaker if necessary */
11248 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
11249 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11250 HDA_AMP_MUTE, mute);
11251 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
11252 HDA_AMP_MUTE, mute);
11253 }
11254}
11255
11256/* unsolicited event for HP jack sensing */
11257static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
11258 unsigned int res)
11259{
11260 if ((res >> 26) != ALC_HP_EVENT)
11261 return;
11262 alc262_lenovo_3000_automute(codec, 1);
11263}
11264
Takashi Iwai8de56b72009-07-24 16:51:47 +020011265static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
11266 int dir, int idx, long *valp)
11267{
11268 int i, change = 0;
11269
11270 for (i = 0; i < 2; i++, valp++)
11271 change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
11272 HDA_AMP_MUTE,
11273 *valp ? 0 : HDA_AMP_MUTE);
11274 return change;
11275}
11276
Takashi Iwai834be882006-03-01 14:16:17 +010011277/* bind hp and internal speaker mute (with plug check) */
11278static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
11279 struct snd_ctl_elem_value *ucontrol)
11280{
11281 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11282 long *valp = ucontrol->value.integer.value;
11283 int change;
11284
Takashi Iwai8de56b72009-07-24 16:51:47 +020011285 change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
11286 change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
Takashi Iwai82beb8f2007-08-10 17:09:26 +020011287 if (change)
11288 alc262_fujitsu_automute(codec, 0);
Takashi Iwai834be882006-03-01 14:16:17 +010011289 return change;
11290}
11291
11292static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
Takashi Iwaicca3b372007-08-10 17:12:15 +020011293 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
Takashi Iwai834be882006-03-01 14:16:17 +010011294 {
11295 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11296 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010011297 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwai834be882006-03-01 14:16:17 +010011298 .info = snd_hda_mixer_amp_switch_info,
11299 .get = snd_hda_mixer_amp_switch_get,
11300 .put = alc262_fujitsu_master_sw_put,
11301 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
11302 },
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010011303 {
11304 .iface = NID_MAPPING,
11305 .name = "Master Playback Switch",
11306 .private_value = 0x1b,
11307 },
Takashi Iwai834be882006-03-01 14:16:17 +010011308 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11309 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11310 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11311 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11312 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011313 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
11314 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
11315 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai834be882006-03-01 14:16:17 +010011316 { } /* end */
11317};
11318
Jiang zhe0e31daf2008-03-20 12:12:39 +010011319/* bind hp and internal speaker mute (with plug check) */
11320static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
11321 struct snd_ctl_elem_value *ucontrol)
11322{
11323 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11324 long *valp = ucontrol->value.integer.value;
11325 int change;
11326
Takashi Iwai8de56b72009-07-24 16:51:47 +020011327 change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
Jiang zhe0e31daf2008-03-20 12:12:39 +010011328 if (change)
11329 alc262_lenovo_3000_automute(codec, 0);
11330 return change;
11331}
11332
11333static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
11334 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
11335 {
11336 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11337 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010011338 .subdevice = HDA_SUBDEV_AMP_FLAG,
Jiang zhe0e31daf2008-03-20 12:12:39 +010011339 .info = snd_hda_mixer_amp_switch_info,
11340 .get = snd_hda_mixer_amp_switch_get,
11341 .put = alc262_lenovo_3000_master_sw_put,
11342 .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
11343 },
11344 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11345 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11346 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11347 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11348 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11349 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
11350 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
11351 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
11352 { } /* end */
11353};
11354
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011355static struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
11356 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
Takashi Iwai42171c12009-05-08 14:11:43 +020011357 ALC262_HIPPO_MASTER_SWITCH,
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011358 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11359 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11360 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11361 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11362 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11363 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
11364 { } /* end */
11365};
11366
Takashi Iwai304dcaa2006-07-25 14:51:16 +020011367/* additional init verbs for Benq laptops */
11368static struct hda_verb alc262_EAPD_verbs[] = {
11369 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
11370 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
11371 {}
11372};
11373
Kailang Yang83c34212007-07-05 11:43:05 +020011374static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
11375 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11376 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11377
11378 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
11379 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
11380 {}
11381};
11382
Tobin Davisf651b502007-10-26 12:40:47 +020011383/* Samsung Q1 Ultra Vista model setup */
11384static struct snd_kcontrol_new alc262_ultra_mixer[] = {
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011385 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11386 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davisf651b502007-10-26 12:40:47 +020011387 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11388 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11389 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011390 HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT),
Tobin Davisf651b502007-10-26 12:40:47 +020011391 { } /* end */
11392};
11393
11394static struct hda_verb alc262_ultra_verbs[] = {
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011395 /* output mixer */
11396 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11397 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11398 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11399 /* speaker */
11400 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11401 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11402 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11403 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
11404 /* HP */
Tobin Davisf651b502007-10-26 12:40:47 +020011405 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011406 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11407 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11408 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11409 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11410 /* internal mic */
11411 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
11412 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11413 /* ADC, choose mic */
11414 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11415 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11416 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11417 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11418 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11419 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11420 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
11421 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
11422 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
11423 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
Tobin Davisf651b502007-10-26 12:40:47 +020011424 {}
11425};
11426
Tobin Davisf651b502007-10-26 12:40:47 +020011427/* mute/unmute internal speaker according to the hp jack and mute state */
11428static void alc262_ultra_automute(struct hda_codec *codec)
11429{
11430 struct alc_spec *spec = codec->spec;
11431 unsigned int mute;
Tobin Davisf651b502007-10-26 12:40:47 +020011432
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011433 mute = 0;
11434 /* auto-mute only when HP is used as HP */
11435 if (!spec->cur_mux[0]) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011436 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011437 if (spec->jack_present)
11438 mute = HDA_AMP_MUTE;
Tobin Davisf651b502007-10-26 12:40:47 +020011439 }
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011440 /* mute/unmute internal speaker */
11441 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11442 HDA_AMP_MUTE, mute);
11443 /* mute/unmute HP */
11444 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
11445 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
Tobin Davisf651b502007-10-26 12:40:47 +020011446}
11447
11448/* unsolicited event for HP jack sensing */
11449static void alc262_ultra_unsol_event(struct hda_codec *codec,
11450 unsigned int res)
11451{
11452 if ((res >> 26) != ALC880_HP_EVENT)
11453 return;
11454 alc262_ultra_automute(codec);
11455}
11456
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011457static struct hda_input_mux alc262_ultra_capture_source = {
11458 .num_items = 2,
11459 .items = {
11460 { "Mic", 0x1 },
11461 { "Headphone", 0x7 },
11462 },
11463};
11464
11465static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
11466 struct snd_ctl_elem_value *ucontrol)
11467{
11468 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11469 struct alc_spec *spec = codec->spec;
11470 int ret;
11471
Takashi Iwai54cbc9a2008-10-31 15:24:04 +010011472 ret = alc_mux_enum_put(kcontrol, ucontrol);
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011473 if (!ret)
11474 return 0;
11475 /* reprogram the HP pin as mic or HP according to the input source */
11476 snd_hda_codec_write_cache(codec, 0x15, 0,
11477 AC_VERB_SET_PIN_WIDGET_CONTROL,
11478 spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
11479 alc262_ultra_automute(codec); /* mute/unmute HP */
11480 return ret;
11481}
11482
11483static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
11484 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
11485 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
11486 {
11487 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11488 .name = "Capture Source",
Takashi Iwai54cbc9a2008-10-31 15:24:04 +010011489 .info = alc_mux_enum_info,
11490 .get = alc_mux_enum_get,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011491 .put = alc262_ultra_mux_enum_put,
11492 },
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010011493 {
11494 .iface = NID_MAPPING,
11495 .name = "Capture Source",
11496 .private_value = 0x15,
11497 },
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011498 { } /* end */
11499};
11500
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011501/* We use two mixers depending on the output pin; 0x16 is a mono output
11502 * and thus it's bound with a different mixer.
11503 * This function returns which mixer amp should be used.
11504 */
11505static int alc262_check_volbit(hda_nid_t nid)
11506{
11507 if (!nid)
11508 return 0;
11509 else if (nid == 0x16)
11510 return 2;
11511 else
11512 return 1;
11513}
11514
11515static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
11516 const char *pfx, int *vbits)
11517{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011518 unsigned long val;
11519 int vbit;
11520
11521 vbit = alc262_check_volbit(nid);
11522 if (!vbit)
11523 return 0;
11524 if (*vbits & vbit) /* a volume control for this mixer already there */
11525 return 0;
11526 *vbits |= vbit;
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011527 if (vbit == 2)
11528 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
11529 else
11530 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
Takashi Iwai0afe5f82009-10-02 09:20:00 +020011531 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val);
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011532}
11533
11534static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
11535 const char *pfx)
11536{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011537 unsigned long val;
11538
11539 if (!nid)
11540 return 0;
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011541 if (nid == 0x16)
11542 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
11543 else
11544 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
Takashi Iwai0afe5f82009-10-02 09:20:00 +020011545 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val);
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011546}
11547
Kailang Yangdf694da2005-12-05 19:42:22 +010011548/* add playback controls from the parsed DAC table */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011549static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
11550 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010011551{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011552 const char *pfx;
11553 int vbits;
Kailang Yangdf694da2005-12-05 19:42:22 +010011554 int err;
11555
11556 spec->multiout.num_dacs = 1; /* only use one dac */
11557 spec->multiout.dac_nids = spec->private_dac_nids;
11558 spec->multiout.dac_nids[0] = 2;
11559
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011560 if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
11561 pfx = "Master";
11562 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
11563 pfx = "Speaker";
11564 else
11565 pfx = "Front";
11566 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx);
11567 if (err < 0)
11568 return err;
11569 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker");
11570 if (err < 0)
11571 return err;
11572 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone");
11573 if (err < 0)
11574 return err;
Kailang Yangdf694da2005-12-05 19:42:22 +010011575
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011576 vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
11577 alc262_check_volbit(cfg->speaker_pins[0]) |
11578 alc262_check_volbit(cfg->hp_pins[0]);
11579 if (vbits == 1 || vbits == 2)
11580 pfx = "Master"; /* only one mixer is used */
11581 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
11582 pfx = "Speaker";
11583 else
11584 pfx = "Front";
11585 vbits = 0;
11586 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits);
11587 if (err < 0)
11588 return err;
11589 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker",
11590 &vbits);
11591 if (err < 0)
11592 return err;
11593 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone",
11594 &vbits);
11595 if (err < 0)
11596 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011597 return 0;
Kailang Yangdf694da2005-12-05 19:42:22 +010011598}
11599
Takashi Iwai05f5f472009-08-25 13:10:18 +020011600#define alc262_auto_create_input_ctls \
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +010011601 alc882_auto_create_input_ctls
Kailang Yangdf694da2005-12-05 19:42:22 +010011602
11603/*
11604 * generic initialization of ADC, input mixers and output mixers
11605 */
11606static struct hda_verb alc262_volume_init_verbs[] = {
11607 /*
11608 * Unmute ADC0-2 and set the default input to mic-in
11609 */
11610 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11611 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11612 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11613 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11614 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11615 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11616
Takashi Iwaicb53c622007-08-10 17:21:45 +020011617 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangdf694da2005-12-05 19:42:22 +010011618 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011619 * Note: PASD motherboards uses the Line In 2 as the input for
11620 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +010011621 */
11622 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011623 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11624 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11625 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11626 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11627 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +010011628
11629 /*
11630 * Set up output mixers (0x0c - 0x0f)
11631 */
11632 /* set vol=0 to output mixers */
11633 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11634 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11635 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yangea1fb292008-08-26 12:58:38 +020011636
Kailang Yangdf694da2005-12-05 19:42:22 +010011637 /* set up input amps for analog loopback */
11638 /* Amp Indices: DAC = 0, mixer = 1 */
11639 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11640 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11641 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11642 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11643 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11644 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11645
11646 /* FIXME: use matrix-type input source selection */
11647 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11648 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11649 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11650 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11651 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11652 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11653 /* Input mixer2 */
11654 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11655 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11656 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11657 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11658 /* Input mixer3 */
11659 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11660 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11661 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11662 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11663
11664 { }
11665};
11666
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011667static struct hda_verb alc262_HP_BPC_init_verbs[] = {
11668 /*
11669 * Unmute ADC0-2 and set the default input to mic-in
11670 */
11671 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11672 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11673 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11674 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11675 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11676 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11677
Takashi Iwaicb53c622007-08-10 17:21:45 +020011678 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011679 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011680 * Note: PASD motherboards uses the Line In 2 as the input for
11681 * front panel mic (mic 2)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011682 */
11683 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011684 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11685 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11686 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11687 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11688 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11689 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
11690 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
Kailang Yangea1fb292008-08-26 12:58:38 +020011691
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011692 /*
11693 * Set up output mixers (0x0c - 0x0e)
11694 */
11695 /* set vol=0 to output mixers */
11696 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11697 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11698 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11699
11700 /* set up input amps for analog loopback */
11701 /* Amp Indices: DAC = 0, mixer = 1 */
11702 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11703 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11704 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11705 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11706 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11707 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11708
Takashi Iwaice875f02008-01-28 18:17:43 +010011709 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011710 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
11711 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
11712
11713 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11714 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11715
11716 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11717 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11718
11719 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11720 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11721 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11722 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11723 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11724
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011725 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011726 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11727 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011728 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011729 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11730 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11731
11732
11733 /* FIXME: use matrix-type input source selection */
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011734 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 0b, 12 */
11735 /* Input mixer1: only unmute Mic */
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011736 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011737 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
11738 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11739 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11740 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11741 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
11742 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
11743 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
11744 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011745 /* Input mixer2 */
11746 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011747 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
11748 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11749 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11750 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11751 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
11752 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
11753 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
11754 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011755 /* Input mixer3 */
11756 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011757 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
11758 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11759 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11760 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11761 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
11762 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
11763 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
11764 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011765
Takashi Iwaice875f02008-01-28 18:17:43 +010011766 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
11767
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011768 { }
11769};
11770
Kailang Yangcd7509a2007-01-26 18:33:17 +010011771static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
11772 /*
11773 * Unmute ADC0-2 and set the default input to mic-in
11774 */
11775 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11776 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11777 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11778 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11779 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11780 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11781
Takashi Iwaicb53c622007-08-10 17:21:45 +020011782 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangcd7509a2007-01-26 18:33:17 +010011783 * mixer widget
11784 * Note: PASD motherboards uses the Line In 2 as the input for front
11785 * panel mic (mic 2)
11786 */
11787 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011788 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11789 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11790 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11791 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11792 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11793 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
11794 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
11795 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Kailang Yangcd7509a2007-01-26 18:33:17 +010011796 /*
11797 * Set up output mixers (0x0c - 0x0e)
11798 */
11799 /* set vol=0 to output mixers */
11800 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11801 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11802 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11803
11804 /* set up input amps for analog loopback */
11805 /* Amp Indices: DAC = 0, mixer = 1 */
11806 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11807 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11808 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11809 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11810 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11811 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11812
11813
11814 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */
11815 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */
11816 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */
11817 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */
11818 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
11819 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */
11820 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */
11821
11822 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11823 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11824
11825 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11826 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
11827
11828 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
11829 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11830 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11831 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
11832 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11833 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11834
11835 /* FIXME: use matrix-type input source selection */
11836 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11837 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11838 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
11839 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
11840 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
11841 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
11842 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
11843 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
11844 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
11845 /* Input mixer2 */
11846 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11847 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11848 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
11849 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
11850 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
11851 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
11852 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
11853 /* Input mixer3 */
11854 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11855 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11856 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
11857 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
11858 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
11859 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
11860 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
11861
Takashi Iwaice875f02008-01-28 18:17:43 +010011862 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
11863
Kailang Yangcd7509a2007-01-26 18:33:17 +010011864 { }
11865};
11866
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011867static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
11868
11869 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Front Speaker */
11870 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11871 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
11872
11873 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* MIC jack */
11874 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
11875 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
11876 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
11877
11878 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP jack */
11879 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11880 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11881 {}
11882};
11883
11884
Takashi Iwaicb53c622007-08-10 17:21:45 +020011885#ifdef CONFIG_SND_HDA_POWER_SAVE
11886#define alc262_loopbacks alc880_loopbacks
11887#endif
11888
Sasha Alexandrdef319f2009-06-16 16:00:15 -040011889/* pcm configuration: identical with ALC880 */
Kailang Yangdf694da2005-12-05 19:42:22 +010011890#define alc262_pcm_analog_playback alc880_pcm_analog_playback
11891#define alc262_pcm_analog_capture alc880_pcm_analog_capture
11892#define alc262_pcm_digital_playback alc880_pcm_digital_playback
11893#define alc262_pcm_digital_capture alc880_pcm_digital_capture
11894
11895/*
11896 * BIOS auto configuration
11897 */
11898static int alc262_parse_auto_config(struct hda_codec *codec)
11899{
11900 struct alc_spec *spec = codec->spec;
11901 int err;
11902 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
11903
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011904 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
11905 alc262_ignore);
11906 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010011907 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011908 if (!spec->autocfg.line_outs) {
Takashi Iwai0852d7a2009-02-11 11:35:15 +010011909 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011910 spec->multiout.max_channels = 2;
11911 spec->no_analog = 1;
11912 goto dig_only;
11913 }
Kailang Yangdf694da2005-12-05 19:42:22 +010011914 return 0; /* can't find valid BIOS pin config */
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011915 }
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011916 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
11917 if (err < 0)
11918 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020011919 err = alc262_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011920 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010011921 return err;
11922
11923 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
11924
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011925 dig_only:
Takashi Iwai0852d7a2009-02-11 11:35:15 +010011926 if (spec->autocfg.dig_outs) {
Kailang Yangdf694da2005-12-05 19:42:22 +010011927 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
Takashi Iwai0852d7a2009-02-11 11:35:15 +010011928 spec->dig_out_type = spec->autocfg.dig_out_type[0];
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011929 }
Kailang Yangdf694da2005-12-05 19:42:22 +010011930 if (spec->autocfg.dig_in_pin)
11931 spec->dig_in_nid = ALC262_DIGIN_NID;
11932
Takashi Iwai603c4012008-07-30 15:01:44 +020011933 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010011934 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +010011935
Takashi Iwaid88897e2008-10-31 15:01:37 +010011936 add_verb(spec, alc262_volume_init_verbs);
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +020011937 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020011938 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +010011939
Takashi Iwai776e1842007-08-29 15:07:11 +020011940 err = alc_auto_add_mic_boost(codec);
11941 if (err < 0)
11942 return err;
11943
Kailang Yang6227cdc2010-02-25 08:36:52 +010011944 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020011945
Kailang Yangdf694da2005-12-05 19:42:22 +010011946 return 1;
11947}
11948
11949#define alc262_auto_init_multi_out alc882_auto_init_multi_out
11950#define alc262_auto_init_hp_out alc882_auto_init_hp_out
11951#define alc262_auto_init_analog_input alc882_auto_init_analog_input
Takashi Iwaif511b012008-08-15 16:46:42 +020011952#define alc262_auto_init_input_src alc882_auto_init_input_src
Kailang Yangdf694da2005-12-05 19:42:22 +010011953
11954
11955/* init callback for auto-configuration model -- overriding the default init */
Takashi Iwaiae6b8132006-03-03 16:47:17 +010011956static void alc262_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +010011957{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010011958 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010011959 alc262_auto_init_multi_out(codec);
11960 alc262_auto_init_hp_out(codec);
11961 alc262_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020011962 alc262_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010011963 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020011964 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010011965}
11966
11967/*
11968 * configuration and preset
11969 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011970static const char *alc262_models[ALC262_MODEL_LAST] = {
11971 [ALC262_BASIC] = "basic",
11972 [ALC262_HIPPO] = "hippo",
11973 [ALC262_HIPPO_1] = "hippo_1",
11974 [ALC262_FUJITSU] = "fujitsu",
11975 [ALC262_HP_BPC] = "hp-bpc",
Kailang Yangcd7509a2007-01-26 18:33:17 +010011976 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
Takashi Iwai61dc35d2007-11-14 12:26:44 +010011977 [ALC262_HP_TC_T5735] = "hp-tc-t5735",
Kailang Yang8c427222008-01-10 13:03:59 +010011978 [ALC262_HP_RP5700] = "hp-rp5700",
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011979 [ALC262_BENQ_ED8] = "benq",
Takashi Iwai0f405022007-07-06 12:24:11 +020011980 [ALC262_BENQ_T31] = "benq-t31",
11981 [ALC262_SONY_ASSAMD] = "sony-assamd",
Takashi Iwai2922c9a2008-08-27 18:12:42 +020011982 [ALC262_TOSHIBA_S06] = "toshiba-s06",
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011983 [ALC262_TOSHIBA_RX1] = "toshiba-rx1",
Tobin Davisf651b502007-10-26 12:40:47 +020011984 [ALC262_ULTRA] = "ultra",
Jiang zhe0e31daf2008-03-20 12:12:39 +010011985 [ALC262_LENOVO_3000] = "lenovo-3000",
Pascal Terjane8f9ae22008-08-04 14:36:05 +020011986 [ALC262_NEC] = "nec",
Tony Vroonba340e82009-02-02 19:01:30 +000011987 [ALC262_TYAN] = "tyan",
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011988 [ALC262_AUTO] = "auto",
11989};
11990
11991static struct snd_pci_quirk alc262_cfg_tbl[] = {
11992 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
Pascal Terjane8f9ae22008-08-04 14:36:05 +020011993 SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
Takashi Iwaidea0a502009-02-09 17:14:52 +010011994 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
11995 ALC262_HP_BPC),
11996 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
11997 ALC262_HP_BPC),
Takashi Iwai53eff7e2009-02-27 17:49:44 +010011998 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
11999 ALC262_HP_BPC),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012000 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012001 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012002 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012003 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012004 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012005 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012006 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012007 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012008 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
12009 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
12010 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
Kailang Yang66d2a9d2007-11-14 12:06:21 +010012011 SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
12012 ALC262_HP_TC_T5735),
Kailang Yang8c427222008-01-10 13:03:59 +010012013 SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012014 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012015 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012016 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
Takashi Iwaibd6afe32009-03-04 11:30:25 +010012017 SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
Takashi Iwai376b5082009-06-22 11:03:13 +020012018 SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
Daniel T Chen95491d92009-11-08 19:03:55 -050012019 SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
Takashi Iwai12929ba2009-11-17 15:58:35 +010012020 SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
Takashi Iwaic5b51652009-11-17 16:01:58 +010012021#if 0 /* disable the quirk since model=auto works better in recent versions */
Takashi Iwaif872a912009-02-26 00:57:01 +010012022 SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
12023 ALC262_SONY_ASSAMD),
Takashi Iwaic5b51652009-11-17 16:01:58 +010012024#endif
Akio Idehara36ca6e12008-06-09 22:57:40 +090012025 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012026 ALC262_TOSHIBA_RX1),
Kailang Yang80ffe862008-10-15 11:23:27 +020012027 SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012028 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
Tony Vroon3f1eeae2008-02-25 16:44:13 +010012029 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
Tony Vroonba340e82009-02-02 19:01:30 +000012030 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
Takashi Iwaidea0a502009-02-09 17:14:52 +010012031 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
12032 ALC262_ULTRA),
Luke Yelavich3e420e72008-12-16 12:37:47 +110012033 SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
Jiang zhe0e31daf2008-03-20 12:12:39 +010012034 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012035 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
Kailang Yang83c34212007-07-05 11:43:05 +020012036 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012037 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
Kailang Yangdf694da2005-12-05 19:42:22 +010012038 {}
12039};
12040
12041static struct alc_config_preset alc262_presets[] = {
12042 [ALC262_BASIC] = {
12043 .mixers = { alc262_base_mixer },
12044 .init_verbs = { alc262_init_verbs },
12045 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12046 .dac_nids = alc262_dac_nids,
12047 .hp_nid = 0x03,
12048 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12049 .channel_mode = alc262_modes,
Takashi Iwaia3bcba32005-12-06 19:05:29 +010012050 .input_mux = &alc262_capture_source,
Kailang Yangdf694da2005-12-05 19:42:22 +010012051 },
Kailang Yangccc656c2006-10-17 12:32:26 +020012052 [ALC262_HIPPO] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020012053 .mixers = { alc262_hippo_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +020012054 .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +020012055 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12056 .dac_nids = alc262_dac_nids,
12057 .hp_nid = 0x03,
12058 .dig_out_nid = ALC262_DIGOUT_NID,
12059 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12060 .channel_mode = alc262_modes,
12061 .input_mux = &alc262_capture_source,
12062 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012063 .setup = alc262_hippo_setup,
12064 .init_hook = alc262_hippo_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +020012065 },
12066 [ALC262_HIPPO_1] = {
12067 .mixers = { alc262_hippo1_mixer },
12068 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
12069 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12070 .dac_nids = alc262_dac_nids,
12071 .hp_nid = 0x02,
12072 .dig_out_nid = ALC262_DIGOUT_NID,
12073 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12074 .channel_mode = alc262_modes,
12075 .input_mux = &alc262_capture_source,
Takashi Iwai42171c12009-05-08 14:11:43 +020012076 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012077 .setup = alc262_hippo1_setup,
12078 .init_hook = alc262_hippo_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +020012079 },
Takashi Iwai834be882006-03-01 14:16:17 +010012080 [ALC262_FUJITSU] = {
12081 .mixers = { alc262_fujitsu_mixer },
Takashi Iwai39d3ed32007-10-12 15:03:48 +020012082 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
12083 alc262_fujitsu_unsol_verbs },
Takashi Iwai834be882006-03-01 14:16:17 +010012084 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12085 .dac_nids = alc262_dac_nids,
12086 .hp_nid = 0x03,
12087 .dig_out_nid = ALC262_DIGOUT_NID,
12088 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12089 .channel_mode = alc262_modes,
12090 .input_mux = &alc262_fujitsu_capture_source,
Takashi Iwaiae6b8132006-03-03 16:47:17 +010012091 .unsol_event = alc262_fujitsu_unsol_event,
Takashi Iwaiebc7a402008-05-20 09:23:05 +020012092 .init_hook = alc262_fujitsu_init_hook,
Takashi Iwai834be882006-03-01 14:16:17 +010012093 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012094 [ALC262_HP_BPC] = {
12095 .mixers = { alc262_HP_BPC_mixer },
12096 .init_verbs = { alc262_HP_BPC_init_verbs },
12097 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12098 .dac_nids = alc262_dac_nids,
12099 .hp_nid = 0x03,
12100 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12101 .channel_mode = alc262_modes,
12102 .input_mux = &alc262_HP_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010012103 .unsol_event = alc262_hp_bpc_unsol_event,
12104 .init_hook = alc262_hp_bpc_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012105 },
Kailang Yangcd7509a2007-01-26 18:33:17 +010012106 [ALC262_HP_BPC_D7000_WF] = {
12107 .mixers = { alc262_HP_BPC_WildWest_mixer },
12108 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
12109 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12110 .dac_nids = alc262_dac_nids,
12111 .hp_nid = 0x03,
12112 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12113 .channel_mode = alc262_modes,
zhejiangaccbe492007-08-31 12:36:05 +020012114 .input_mux = &alc262_HP_D7000_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010012115 .unsol_event = alc262_hp_wildwest_unsol_event,
12116 .init_hook = alc262_hp_wildwest_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012117 },
Kailang Yangcd7509a2007-01-26 18:33:17 +010012118 [ALC262_HP_BPC_D7000_WL] = {
12119 .mixers = { alc262_HP_BPC_WildWest_mixer,
12120 alc262_HP_BPC_WildWest_option_mixer },
12121 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
12122 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12123 .dac_nids = alc262_dac_nids,
12124 .hp_nid = 0x03,
12125 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12126 .channel_mode = alc262_modes,
zhejiangaccbe492007-08-31 12:36:05 +020012127 .input_mux = &alc262_HP_D7000_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010012128 .unsol_event = alc262_hp_wildwest_unsol_event,
12129 .init_hook = alc262_hp_wildwest_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012130 },
Kailang Yang66d2a9d2007-11-14 12:06:21 +010012131 [ALC262_HP_TC_T5735] = {
12132 .mixers = { alc262_hp_t5735_mixer },
12133 .init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
12134 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12135 .dac_nids = alc262_dac_nids,
12136 .hp_nid = 0x03,
12137 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12138 .channel_mode = alc262_modes,
12139 .input_mux = &alc262_capture_source,
Takashi Iwaidc99be42010-01-20 08:35:06 +010012140 .unsol_event = alc_sku_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012141 .setup = alc262_hp_t5735_setup,
Takashi Iwaidc99be42010-01-20 08:35:06 +010012142 .init_hook = alc_inithook,
Kailang Yang8c427222008-01-10 13:03:59 +010012143 },
12144 [ALC262_HP_RP5700] = {
12145 .mixers = { alc262_hp_rp5700_mixer },
12146 .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
12147 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12148 .dac_nids = alc262_dac_nids,
12149 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12150 .channel_mode = alc262_modes,
12151 .input_mux = &alc262_hp_rp5700_capture_source,
Kailang Yang66d2a9d2007-11-14 12:06:21 +010012152 },
Takashi Iwai304dcaa2006-07-25 14:51:16 +020012153 [ALC262_BENQ_ED8] = {
12154 .mixers = { alc262_base_mixer },
12155 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
12156 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12157 .dac_nids = alc262_dac_nids,
12158 .hp_nid = 0x03,
12159 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12160 .channel_mode = alc262_modes,
12161 .input_mux = &alc262_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012162 },
Kailang Yang272a5272007-05-14 11:00:38 +020012163 [ALC262_SONY_ASSAMD] = {
12164 .mixers = { alc262_sony_mixer },
12165 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
12166 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12167 .dac_nids = alc262_dac_nids,
12168 .hp_nid = 0x02,
12169 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12170 .channel_mode = alc262_modes,
12171 .input_mux = &alc262_capture_source,
12172 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012173 .setup = alc262_hippo_setup,
12174 .init_hook = alc262_hippo_automute,
Kailang Yang83c34212007-07-05 11:43:05 +020012175 },
12176 [ALC262_BENQ_T31] = {
12177 .mixers = { alc262_benq_t31_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +020012178 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
12179 alc_hp15_unsol_verbs },
Kailang Yang83c34212007-07-05 11:43:05 +020012180 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12181 .dac_nids = alc262_dac_nids,
12182 .hp_nid = 0x03,
12183 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12184 .channel_mode = alc262_modes,
12185 .input_mux = &alc262_capture_source,
12186 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012187 .setup = alc262_hippo_setup,
12188 .init_hook = alc262_hippo_automute,
Kailang Yangea1fb292008-08-26 12:58:38 +020012189 },
Tobin Davisf651b502007-10-26 12:40:47 +020012190 [ALC262_ULTRA] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010012191 .mixers = { alc262_ultra_mixer },
12192 .cap_mixer = alc262_ultra_capture_mixer,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010012193 .init_verbs = { alc262_ultra_verbs },
Tobin Davisf651b502007-10-26 12:40:47 +020012194 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12195 .dac_nids = alc262_dac_nids,
Tobin Davisf651b502007-10-26 12:40:47 +020012196 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12197 .channel_mode = alc262_modes,
12198 .input_mux = &alc262_ultra_capture_source,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010012199 .adc_nids = alc262_adc_nids, /* ADC0 */
12200 .capsrc_nids = alc262_capsrc_nids,
12201 .num_adc_nids = 1, /* single ADC */
Tobin Davisf651b502007-10-26 12:40:47 +020012202 .unsol_event = alc262_ultra_unsol_event,
12203 .init_hook = alc262_ultra_automute,
12204 },
Jiang zhe0e31daf2008-03-20 12:12:39 +010012205 [ALC262_LENOVO_3000] = {
12206 .mixers = { alc262_lenovo_3000_mixer },
12207 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
Daniel T Chene2595322009-12-19 18:19:02 -050012208 alc262_lenovo_3000_unsol_verbs,
12209 alc262_lenovo_3000_init_verbs },
Jiang zhe0e31daf2008-03-20 12:12:39 +010012210 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12211 .dac_nids = alc262_dac_nids,
12212 .hp_nid = 0x03,
12213 .dig_out_nid = ALC262_DIGOUT_NID,
12214 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12215 .channel_mode = alc262_modes,
12216 .input_mux = &alc262_fujitsu_capture_source,
12217 .unsol_event = alc262_lenovo_3000_unsol_event,
12218 },
Pascal Terjane8f9ae22008-08-04 14:36:05 +020012219 [ALC262_NEC] = {
12220 .mixers = { alc262_nec_mixer },
12221 .init_verbs = { alc262_nec_verbs },
12222 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12223 .dac_nids = alc262_dac_nids,
12224 .hp_nid = 0x03,
12225 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12226 .channel_mode = alc262_modes,
12227 .input_mux = &alc262_capture_source,
12228 },
Kailang Yang4e555fe2008-08-26 13:05:55 +020012229 [ALC262_TOSHIBA_S06] = {
12230 .mixers = { alc262_toshiba_s06_mixer },
12231 .init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
12232 alc262_eapd_verbs },
12233 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12234 .capsrc_nids = alc262_dmic_capsrc_nids,
12235 .dac_nids = alc262_dac_nids,
12236 .adc_nids = alc262_dmic_adc_nids, /* ADC0 */
Takashi Iwaiae14ef62009-06-22 08:16:56 +020012237 .num_adc_nids = 1, /* single ADC */
Kailang Yang4e555fe2008-08-26 13:05:55 +020012238 .dig_out_nid = ALC262_DIGOUT_NID,
12239 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12240 .channel_mode = alc262_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012241 .unsol_event = alc_sku_unsol_event,
12242 .setup = alc262_toshiba_s06_setup,
12243 .init_hook = alc_inithook,
Kailang Yang4e555fe2008-08-26 13:05:55 +020012244 },
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012245 [ALC262_TOSHIBA_RX1] = {
12246 .mixers = { alc262_toshiba_rx1_mixer },
12247 .init_verbs = { alc262_init_verbs, alc262_toshiba_rx1_unsol_verbs },
12248 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12249 .dac_nids = alc262_dac_nids,
12250 .hp_nid = 0x03,
12251 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12252 .channel_mode = alc262_modes,
12253 .input_mux = &alc262_capture_source,
12254 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012255 .setup = alc262_hippo_setup,
12256 .init_hook = alc262_hippo_automute,
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012257 },
Tony Vroonba340e82009-02-02 19:01:30 +000012258 [ALC262_TYAN] = {
12259 .mixers = { alc262_tyan_mixer },
12260 .init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
12261 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12262 .dac_nids = alc262_dac_nids,
12263 .hp_nid = 0x02,
12264 .dig_out_nid = ALC262_DIGOUT_NID,
12265 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12266 .channel_mode = alc262_modes,
12267 .input_mux = &alc262_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012268 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012269 .setup = alc262_tyan_setup,
12270 .init_hook = alc_automute_amp,
Tony Vroonba340e82009-02-02 19:01:30 +000012271 },
Kailang Yangdf694da2005-12-05 19:42:22 +010012272};
12273
12274static int patch_alc262(struct hda_codec *codec)
12275{
12276 struct alc_spec *spec;
12277 int board_config;
12278 int err;
12279
Robert P. J. Daydc041e02006-12-19 14:44:15 +010012280 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yangdf694da2005-12-05 19:42:22 +010012281 if (spec == NULL)
12282 return -ENOMEM;
12283
12284 codec->spec = spec;
12285#if 0
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012286 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
12287 * under-run
12288 */
Kailang Yangdf694da2005-12-05 19:42:22 +010012289 {
12290 int tmp;
12291 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
12292 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
12293 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
12294 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
12295 }
12296#endif
12297
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +020012298 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
12299
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012300 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
12301 alc262_models,
12302 alc262_cfg_tbl);
Kailang Yangcd7509a2007-01-26 18:33:17 +010012303
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012304 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020012305 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
12306 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +010012307 board_config = ALC262_AUTO;
12308 }
12309
12310 if (board_config == ALC262_AUTO) {
12311 /* automatic parse from the BIOS config */
12312 err = alc262_parse_auto_config(codec);
12313 if (err < 0) {
12314 alc_free(codec);
12315 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012316 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012317 printk(KERN_INFO
12318 "hda_codec: Cannot set up configuration "
12319 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +010012320 board_config = ALC262_BASIC;
12321 }
12322 }
12323
Takashi Iwai07eba612009-02-19 08:06:35 +010012324 if (!spec->no_analog) {
12325 err = snd_hda_attach_beep_device(codec, 0x1);
12326 if (err < 0) {
12327 alc_free(codec);
12328 return err;
12329 }
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090012330 }
12331
Kailang Yangdf694da2005-12-05 19:42:22 +010012332 if (board_config != ALC262_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020012333 setup_preset(codec, &alc262_presets[board_config]);
Kailang Yangdf694da2005-12-05 19:42:22 +010012334
Kailang Yangdf694da2005-12-05 19:42:22 +010012335 spec->stream_analog_playback = &alc262_pcm_analog_playback;
12336 spec->stream_analog_capture = &alc262_pcm_analog_capture;
Kailang Yangea1fb292008-08-26 12:58:38 +020012337
Kailang Yangdf694da2005-12-05 19:42:22 +010012338 spec->stream_digital_playback = &alc262_pcm_digital_playback;
12339 spec->stream_digital_capture = &alc262_pcm_digital_capture;
12340
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012341 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwai8c927b42009-06-22 10:56:54 +020012342 int i;
12343 /* check whether the digital-mic has to be supported */
12344 for (i = 0; i < spec->input_mux->num_items; i++) {
12345 if (spec->input_mux->items[i].index >= 9)
12346 break;
12347 }
12348 if (i < spec->input_mux->num_items) {
12349 /* use only ADC0 */
12350 spec->adc_nids = alc262_dmic_adc_nids;
12351 spec->num_adc_nids = 1;
12352 spec->capsrc_nids = alc262_dmic_capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +010012353 } else {
Takashi Iwai8c927b42009-06-22 10:56:54 +020012354 /* all analog inputs */
12355 /* check whether NID 0x07 is valid */
12356 unsigned int wcap = get_wcaps(codec, 0x07);
12357
12358 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020012359 wcap = get_wcaps_type(wcap);
Takashi Iwai8c927b42009-06-22 10:56:54 +020012360 if (wcap != AC_WID_AUD_IN) {
12361 spec->adc_nids = alc262_adc_nids_alt;
12362 spec->num_adc_nids =
12363 ARRAY_SIZE(alc262_adc_nids_alt);
12364 spec->capsrc_nids = alc262_capsrc_nids_alt;
12365 } else {
12366 spec->adc_nids = alc262_adc_nids;
12367 spec->num_adc_nids =
12368 ARRAY_SIZE(alc262_adc_nids);
12369 spec->capsrc_nids = alc262_capsrc_nids;
12370 }
Kailang Yangdf694da2005-12-05 19:42:22 +010012371 }
12372 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +010012373 if (!spec->cap_mixer && !spec->no_analog)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020012374 set_capture_mixer(codec);
Takashi Iwai07eba612009-02-19 08:06:35 +010012375 if (!spec->no_analog)
12376 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Kailang Yangdf694da2005-12-05 19:42:22 +010012377
Takashi Iwai2134ea42008-01-10 16:53:55 +010012378 spec->vmaster_nid = 0x0c;
12379
Kailang Yangdf694da2005-12-05 19:42:22 +010012380 codec->patch_ops = alc_patch_ops;
12381 if (board_config == ALC262_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +010012382 spec->init_hook = alc262_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020012383#ifdef CONFIG_SND_HDA_POWER_SAVE
12384 if (!spec->loopback.amplist)
12385 spec->loopback.amplist = alc262_loopbacks;
12386#endif
Kailang Yangea1fb292008-08-26 12:58:38 +020012387
Kailang Yangdf694da2005-12-05 19:42:22 +010012388 return 0;
12389}
12390
Kailang Yangdf694da2005-12-05 19:42:22 +010012391/*
Kailang Yanga361d842007-06-05 12:30:55 +020012392 * ALC268 channel source setting (2 channel)
12393 */
12394#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
12395#define alc268_modes alc260_modes
Kailang Yangea1fb292008-08-26 12:58:38 +020012396
Kailang Yanga361d842007-06-05 12:30:55 +020012397static hda_nid_t alc268_dac_nids[2] = {
12398 /* front, hp */
12399 0x02, 0x03
12400};
12401
12402static hda_nid_t alc268_adc_nids[2] = {
12403 /* ADC0-1 */
12404 0x08, 0x07
12405};
12406
12407static hda_nid_t alc268_adc_nids_alt[1] = {
12408 /* ADC0 */
12409 0x08
12410};
12411
Takashi Iwaie1406342008-02-11 18:32:32 +010012412static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
12413
Kailang Yanga361d842007-06-05 12:30:55 +020012414static struct snd_kcontrol_new alc268_base_mixer[] = {
12415 /* output mixer control */
12416 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12417 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12418 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12419 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwai33bf17a2007-08-21 11:51:42 +020012420 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12421 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
12422 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
Kailang Yanga361d842007-06-05 12:30:55 +020012423 { }
12424};
12425
Takashi Iwai42171c12009-05-08 14:11:43 +020012426static struct snd_kcontrol_new alc268_toshiba_mixer[] = {
12427 /* output mixer control */
12428 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12429 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12430 ALC262_HIPPO_MASTER_SWITCH,
12431 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12432 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
12433 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
12434 { }
12435};
12436
Takashi Iwaiaef9d312008-02-19 13:16:41 +010012437/* bind Beep switches of both NID 0x0f and 0x10 */
12438static struct hda_bind_ctls alc268_bind_beep_sw = {
12439 .ops = &snd_hda_bind_sw,
12440 .values = {
12441 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
12442 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
12443 0
12444 },
12445};
12446
12447static struct snd_kcontrol_new alc268_beep_mixer[] = {
12448 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
12449 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
12450 { }
12451};
12452
Kailang Yangd1a991a2007-08-15 16:21:59 +020012453static struct hda_verb alc268_eapd_verbs[] = {
12454 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
12455 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
12456 { }
12457};
12458
Takashi Iwaid2738092007-08-16 14:59:45 +020012459/* Toshiba specific */
Takashi Iwaid2738092007-08-16 14:59:45 +020012460static struct hda_verb alc268_toshiba_verbs[] = {
12461 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12462 { } /* end */
12463};
12464
12465/* Acer specific */
Takashi Iwai889c4392007-08-23 18:56:52 +020012466/* bind volumes of both NID 0x02 and 0x03 */
Takashi Iwai6bc96852007-08-17 09:02:12 +020012467static struct hda_bind_ctls alc268_acer_bind_master_vol = {
12468 .ops = &snd_hda_bind_vol,
12469 .values = {
12470 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
12471 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
12472 0
12473 },
12474};
12475
Takashi Iwai889c4392007-08-23 18:56:52 +020012476/* mute/unmute internal speaker according to the hp jack and mute state */
12477static void alc268_acer_automute(struct hda_codec *codec, int force)
12478{
12479 struct alc_spec *spec = codec->spec;
12480 unsigned int mute;
12481
12482 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080012483 spec->jack_present = snd_hda_jack_detect(codec, 0x14);
Takashi Iwai889c4392007-08-23 18:56:52 +020012484 spec->sense_updated = 1;
12485 }
12486 if (spec->jack_present)
12487 mute = HDA_AMP_MUTE; /* mute internal speaker */
12488 else /* unmute internal speaker if necessary */
12489 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
12490 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
12491 HDA_AMP_MUTE, mute);
12492}
12493
12494
12495/* bind hp and internal speaker mute (with plug check) */
12496static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
12497 struct snd_ctl_elem_value *ucontrol)
12498{
12499 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
12500 long *valp = ucontrol->value.integer.value;
12501 int change;
12502
Takashi Iwai8de56b72009-07-24 16:51:47 +020012503 change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
Takashi Iwai889c4392007-08-23 18:56:52 +020012504 if (change)
12505 alc268_acer_automute(codec, 0);
12506 return change;
12507}
Takashi Iwaid2738092007-08-16 14:59:45 +020012508
Kailang Yang8ef355d2008-08-26 13:10:22 +020012509static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
12510 /* output mixer control */
12511 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12512 {
12513 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12514 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012515 .subdevice = HDA_SUBDEV_AMP_FLAG,
Kailang Yang8ef355d2008-08-26 13:10:22 +020012516 .info = snd_hda_mixer_amp_switch_info,
12517 .get = snd_hda_mixer_amp_switch_get,
12518 .put = alc268_acer_master_sw_put,
12519 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12520 },
12521 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
12522 { }
12523};
12524
Takashi Iwaid2738092007-08-16 14:59:45 +020012525static struct snd_kcontrol_new alc268_acer_mixer[] = {
12526 /* output mixer control */
12527 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12528 {
12529 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12530 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012531 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwaid2738092007-08-16 14:59:45 +020012532 .info = snd_hda_mixer_amp_switch_info,
12533 .get = snd_hda_mixer_amp_switch_get,
12534 .put = alc268_acer_master_sw_put,
12535 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12536 },
Takashi Iwai33bf17a2007-08-21 11:51:42 +020012537 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12538 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
12539 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
Takashi Iwaid2738092007-08-16 14:59:45 +020012540 { }
12541};
12542
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012543static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
12544 /* output mixer control */
12545 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12546 {
12547 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12548 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012549 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012550 .info = snd_hda_mixer_amp_switch_info,
12551 .get = snd_hda_mixer_amp_switch_get,
12552 .put = alc268_acer_master_sw_put,
12553 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12554 },
12555 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12556 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
12557 { }
12558};
12559
Kailang Yang8ef355d2008-08-26 13:10:22 +020012560static struct hda_verb alc268_acer_aspire_one_verbs[] = {
12561 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
12562 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12563 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12564 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
12565 {0x23, AC_VERB_SET_CONNECT_SEL, 0x06},
12566 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, 0xa017},
12567 { }
12568};
12569
Takashi Iwaid2738092007-08-16 14:59:45 +020012570static struct hda_verb alc268_acer_verbs[] = {
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012571 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
12572 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaid2738092007-08-16 14:59:45 +020012573 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12574 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012575 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
12576 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaid2738092007-08-16 14:59:45 +020012577 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12578 { }
12579};
12580
12581/* unsolicited event for HP jack sensing */
Takashi Iwai42171c12009-05-08 14:11:43 +020012582#define alc268_toshiba_unsol_event alc262_hippo_unsol_event
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012583#define alc268_toshiba_setup alc262_hippo_setup
12584#define alc268_toshiba_automute alc262_hippo_automute
Takashi Iwaid2738092007-08-16 14:59:45 +020012585
12586static void alc268_acer_unsol_event(struct hda_codec *codec,
12587 unsigned int res)
12588{
Takashi Iwai889c4392007-08-23 18:56:52 +020012589 if ((res >> 26) != ALC880_HP_EVENT)
Takashi Iwaid2738092007-08-16 14:59:45 +020012590 return;
12591 alc268_acer_automute(codec, 1);
12592}
12593
Takashi Iwai889c4392007-08-23 18:56:52 +020012594static void alc268_acer_init_hook(struct hda_codec *codec)
12595{
12596 alc268_acer_automute(codec, 1);
12597}
12598
Kailang Yang8ef355d2008-08-26 13:10:22 +020012599/* toggle speaker-output according to the hp-jack state */
12600static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
12601{
12602 unsigned int present;
12603 unsigned char bits;
12604
Wu Fengguang864f92b2009-11-18 12:38:02 +080012605 present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020012606 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yang8ef355d2008-08-26 13:10:22 +020012607 snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020012608 HDA_AMP_MUTE, bits);
Kailang Yang8ef355d2008-08-26 13:10:22 +020012609 snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020012610 HDA_AMP_MUTE, bits);
Kailang Yang8ef355d2008-08-26 13:10:22 +020012611}
12612
Kailang Yang8ef355d2008-08-26 13:10:22 +020012613static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
12614 unsigned int res)
12615{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012616 switch (res >> 26) {
12617 case ALC880_HP_EVENT:
Kailang Yang8ef355d2008-08-26 13:10:22 +020012618 alc268_aspire_one_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012619 break;
12620 case ALC880_MIC_EVENT:
12621 alc_mic_automute(codec);
12622 break;
12623 }
12624}
12625
12626static void alc268_acer_lc_setup(struct hda_codec *codec)
12627{
12628 struct alc_spec *spec = codec->spec;
12629 spec->ext_mic.pin = 0x18;
12630 spec->ext_mic.mux_idx = 0;
12631 spec->int_mic.pin = 0x12;
12632 spec->int_mic.mux_idx = 6;
12633 spec->auto_mic = 1;
Kailang Yang8ef355d2008-08-26 13:10:22 +020012634}
12635
12636static void alc268_acer_lc_init_hook(struct hda_codec *codec)
12637{
12638 alc268_aspire_one_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012639 alc_mic_automute(codec);
Kailang Yang8ef355d2008-08-26 13:10:22 +020012640}
12641
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012642static struct snd_kcontrol_new alc268_dell_mixer[] = {
12643 /* output mixer control */
12644 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
12645 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12646 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
12647 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
12648 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12649 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
12650 { }
12651};
12652
12653static struct hda_verb alc268_dell_verbs[] = {
12654 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12655 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12656 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012657 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012658 { }
12659};
12660
12661/* mute/unmute internal speaker according to the hp jack and mute state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012662static void alc268_dell_setup(struct hda_codec *codec)
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012663{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012664 struct alc_spec *spec = codec->spec;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012665
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012666 spec->autocfg.hp_pins[0] = 0x15;
12667 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012668 spec->ext_mic.pin = 0x18;
12669 spec->ext_mic.mux_idx = 0;
12670 spec->int_mic.pin = 0x19;
12671 spec->int_mic.mux_idx = 1;
12672 spec->auto_mic = 1;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012673}
12674
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012675static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
12676 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12677 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12678 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12679 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
12680 HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12681 HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
12682 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
12683 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
12684 { }
12685};
12686
12687static struct hda_verb alc267_quanta_il1_verbs[] = {
12688 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12689 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
12690 { }
12691};
12692
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012693static void alc267_quanta_il1_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012694{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012695 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012696 spec->autocfg.hp_pins[0] = 0x15;
12697 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012698 spec->ext_mic.pin = 0x18;
12699 spec->ext_mic.mux_idx = 0;
12700 spec->int_mic.pin = 0x19;
12701 spec->int_mic.mux_idx = 1;
12702 spec->auto_mic = 1;
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012703}
12704
Kailang Yanga361d842007-06-05 12:30:55 +020012705/*
12706 * generic initialization of ADC, input mixers and output mixers
12707 */
12708static struct hda_verb alc268_base_init_verbs[] = {
12709 /* Unmute DAC0-1 and set vol = 0 */
12710 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020012711 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020012712
12713 /*
12714 * Set up output mixers (0x0c - 0x0e)
12715 */
12716 /* set vol=0 to output mixers */
12717 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yanga361d842007-06-05 12:30:55 +020012718 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
12719
12720 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12721 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12722
12723 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
12724 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
12725 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
12726 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12727 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12728 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12729 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12730 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12731
12732 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12733 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12734 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12735 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020012736 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwaiaef9d312008-02-19 13:16:41 +010012737
12738 /* set PCBEEP vol = 0, mute connections */
12739 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12740 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12741 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yanga361d842007-06-05 12:30:55 +020012742
Jiang Zhea9b3aa82007-12-20 13:13:13 +010012743 /* Unmute Selector 23h,24h and set the default input to mic-in */
Kailang Yangea1fb292008-08-26 12:58:38 +020012744
Jiang Zhea9b3aa82007-12-20 13:13:13 +010012745 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
12746 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12747 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
12748 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020012749
Kailang Yanga361d842007-06-05 12:30:55 +020012750 { }
12751};
12752
12753/*
12754 * generic initialization of ADC, input mixers and output mixers
12755 */
12756static struct hda_verb alc268_volume_init_verbs[] = {
12757 /* set output DAC */
Takashi Iwai4cfb91c2009-01-23 12:53:09 +010012758 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12759 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020012760
12761 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12762 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12763 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12764 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12765 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12766
Kailang Yanga361d842007-06-05 12:30:55 +020012767 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yanga361d842007-06-05 12:30:55 +020012768 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12769 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12770
12771 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020012772 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020012773
Takashi Iwaiaef9d312008-02-19 13:16:41 +010012774 /* set PCBEEP vol = 0, mute connections */
12775 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12776 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12777 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yanga361d842007-06-05 12:30:55 +020012778
12779 { }
12780};
12781
Takashi Iwaifdbc66262009-08-19 00:18:10 +020012782static struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
12783 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12784 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
12785 { } /* end */
12786};
12787
Kailang Yanga361d842007-06-05 12:30:55 +020012788static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
12789 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12790 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
Takashi Iwaifdbc66262009-08-19 00:18:10 +020012791 _DEFINE_CAPSRC(1),
Kailang Yanga361d842007-06-05 12:30:55 +020012792 { } /* end */
12793};
12794
12795static struct snd_kcontrol_new alc268_capture_mixer[] = {
12796 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12797 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
12798 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
12799 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
Takashi Iwaifdbc66262009-08-19 00:18:10 +020012800 _DEFINE_CAPSRC(2),
Kailang Yanga361d842007-06-05 12:30:55 +020012801 { } /* end */
12802};
12803
12804static struct hda_input_mux alc268_capture_source = {
12805 .num_items = 4,
12806 .items = {
12807 { "Mic", 0x0 },
12808 { "Front Mic", 0x1 },
12809 { "Line", 0x2 },
12810 { "CD", 0x3 },
12811 },
12812};
12813
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012814static struct hda_input_mux alc268_acer_capture_source = {
12815 .num_items = 3,
12816 .items = {
12817 { "Mic", 0x0 },
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012818 { "Internal Mic", 0x1 },
12819 { "Line", 0x2 },
12820 },
12821};
12822
12823static struct hda_input_mux alc268_acer_dmic_capture_source = {
12824 .num_items = 3,
12825 .items = {
12826 { "Mic", 0x0 },
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012827 { "Internal Mic", 0x6 },
12828 { "Line", 0x2 },
12829 },
12830};
12831
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010012832#ifdef CONFIG_SND_DEBUG
12833static struct snd_kcontrol_new alc268_test_mixer[] = {
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010012834 /* Volume widgets */
12835 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
12836 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
12837 HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
12838 HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
12839 HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
12840 HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
12841 HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
12842 HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
12843 HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
12844 HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
12845 HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
12846 HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
12847 HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
Takashi Iwaif0747ee2008-01-15 11:41:41 +010012848 /* The below appears problematic on some hardwares */
12849 /*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010012850 HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12851 HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
12852 HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
12853 HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
12854
12855 /* Modes for retasking pin widgets */
12856 ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
12857 ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
12858 ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
12859 ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
12860
12861 /* Controls for GPIO pins, assuming they are configured as outputs */
12862 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
12863 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
12864 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
12865 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
12866
12867 /* Switches to allow the digital SPDIF output pin to be enabled.
12868 * The ALC268 does not have an SPDIF input.
12869 */
12870 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
12871
12872 /* A switch allowing EAPD to be enabled. Some laptops seem to use
12873 * this output to turn on an external amplifier.
12874 */
12875 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
12876 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
12877
12878 { } /* end */
12879};
12880#endif
12881
Kailang Yanga361d842007-06-05 12:30:55 +020012882/* create input playback/capture controls for the given pin */
12883static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
12884 const char *ctlname, int idx)
12885{
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012886 hda_nid_t dac;
Kailang Yanga361d842007-06-05 12:30:55 +020012887 int err;
12888
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012889 switch (nid) {
12890 case 0x14:
12891 case 0x16:
12892 dac = 0x02;
12893 break;
12894 case 0x15:
Kailang Yang531d8792010-04-09 10:57:33 +020012895 case 0x21: /* ALC269vb has this pin, too */
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012896 dac = 0x03;
12897 break;
12898 default:
12899 return 0;
12900 }
12901 if (spec->multiout.dac_nids[0] != dac &&
12902 spec->multiout.dac_nids[1] != dac) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012903 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012904 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
Kailang Yanga361d842007-06-05 12:30:55 +020012905 HDA_OUTPUT));
12906 if (err < 0)
12907 return err;
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012908 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
12909 }
12910
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012911 if (nid != 0x16)
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012912 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
Kailang Yanga361d842007-06-05 12:30:55 +020012913 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012914 else /* mono */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012915 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012916 HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
Kailang Yanga361d842007-06-05 12:30:55 +020012917 if (err < 0)
12918 return err;
12919 return 0;
12920}
12921
12922/* add playback controls from the parsed DAC table */
12923static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
12924 const struct auto_pin_cfg *cfg)
12925{
12926 hda_nid_t nid;
12927 int err;
12928
Kailang Yanga361d842007-06-05 12:30:55 +020012929 spec->multiout.dac_nids = spec->private_dac_nids;
Kailang Yanga361d842007-06-05 12:30:55 +020012930
12931 nid = cfg->line_out_pins[0];
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012932 if (nid) {
12933 const char *name;
12934 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
12935 name = "Speaker";
12936 else
12937 name = "Front";
12938 err = alc268_new_analog_output(spec, nid, name, 0);
12939 if (err < 0)
12940 return err;
12941 }
Kailang Yanga361d842007-06-05 12:30:55 +020012942
12943 nid = cfg->speaker_pins[0];
12944 if (nid == 0x1d) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012945 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
Kailang Yanga361d842007-06-05 12:30:55 +020012946 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
12947 if (err < 0)
12948 return err;
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012949 } else {
12950 err = alc268_new_analog_output(spec, nid, "Speaker", 0);
12951 if (err < 0)
12952 return err;
Kailang Yanga361d842007-06-05 12:30:55 +020012953 }
12954 nid = cfg->hp_pins[0];
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012955 if (nid) {
12956 err = alc268_new_analog_output(spec, nid, "Headphone", 0);
12957 if (err < 0)
12958 return err;
12959 }
Kailang Yanga361d842007-06-05 12:30:55 +020012960
12961 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
12962 if (nid == 0x16) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012963 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012964 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
Kailang Yanga361d842007-06-05 12:30:55 +020012965 if (err < 0)
12966 return err;
12967 }
Kailang Yangea1fb292008-08-26 12:58:38 +020012968 return 0;
Kailang Yanga361d842007-06-05 12:30:55 +020012969}
12970
12971/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020012972static int alc268_auto_create_input_ctls(struct hda_codec *codec,
Kailang Yanga361d842007-06-05 12:30:55 +020012973 const struct auto_pin_cfg *cfg)
12974{
Takashi Iwai05f5f472009-08-25 13:10:18 +020012975 return alc_auto_create_input_ctls(codec, cfg, 0, 0x23, 0x24);
Kailang Yanga361d842007-06-05 12:30:55 +020012976}
12977
Takashi Iwaie9af4f32009-08-29 23:23:08 +020012978static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
12979 hda_nid_t nid, int pin_type)
12980{
12981 int idx;
12982
12983 alc_set_pin_output(codec, nid, pin_type);
12984 if (nid == 0x14 || nid == 0x16)
12985 idx = 0;
12986 else
12987 idx = 1;
12988 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
12989}
12990
12991static void alc268_auto_init_multi_out(struct hda_codec *codec)
12992{
12993 struct alc_spec *spec = codec->spec;
12994 hda_nid_t nid = spec->autocfg.line_out_pins[0];
12995 if (nid) {
12996 int pin_type = get_pin_type(spec->autocfg.line_out_type);
12997 alc268_auto_set_output_and_unmute(codec, nid, pin_type);
12998 }
12999}
13000
13001static void alc268_auto_init_hp_out(struct hda_codec *codec)
13002{
13003 struct alc_spec *spec = codec->spec;
13004 hda_nid_t pin;
13005
13006 pin = spec->autocfg.hp_pins[0];
13007 if (pin)
13008 alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
13009 pin = spec->autocfg.speaker_pins[0];
13010 if (pin)
13011 alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
13012}
13013
Kailang Yanga361d842007-06-05 12:30:55 +020013014static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
13015{
13016 struct alc_spec *spec = codec->spec;
13017 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
13018 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
13019 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
13020 unsigned int dac_vol1, dac_vol2;
13021
Takashi Iwaie9af4f32009-08-29 23:23:08 +020013022 if (line_nid == 0x1d || speaker_nid == 0x1d) {
Kailang Yanga361d842007-06-05 12:30:55 +020013023 snd_hda_codec_write(codec, speaker_nid, 0,
13024 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
Takashi Iwaie9af4f32009-08-29 23:23:08 +020013025 /* mute mixer inputs from 0x1d */
Kailang Yanga361d842007-06-05 12:30:55 +020013026 snd_hda_codec_write(codec, 0x0f, 0,
13027 AC_VERB_SET_AMP_GAIN_MUTE,
13028 AMP_IN_UNMUTE(1));
13029 snd_hda_codec_write(codec, 0x10, 0,
13030 AC_VERB_SET_AMP_GAIN_MUTE,
13031 AMP_IN_UNMUTE(1));
13032 } else {
Takashi Iwaie9af4f32009-08-29 23:23:08 +020013033 /* unmute mixer inputs from 0x1d */
Kailang Yanga361d842007-06-05 12:30:55 +020013034 snd_hda_codec_write(codec, 0x0f, 0,
13035 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
13036 snd_hda_codec_write(codec, 0x10, 0,
13037 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
13038 }
13039
13040 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */
Kailang Yangea1fb292008-08-26 12:58:38 +020013041 if (line_nid == 0x14)
Kailang Yanga361d842007-06-05 12:30:55 +020013042 dac_vol2 = AMP_OUT_ZERO;
13043 else if (line_nid == 0x15)
13044 dac_vol1 = AMP_OUT_ZERO;
Kailang Yangea1fb292008-08-26 12:58:38 +020013045 if (hp_nid == 0x14)
Kailang Yanga361d842007-06-05 12:30:55 +020013046 dac_vol2 = AMP_OUT_ZERO;
13047 else if (hp_nid == 0x15)
13048 dac_vol1 = AMP_OUT_ZERO;
13049 if (line_nid != 0x16 || hp_nid != 0x16 ||
13050 spec->autocfg.line_out_pins[1] != 0x16 ||
13051 spec->autocfg.line_out_pins[2] != 0x16)
13052 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
13053
13054 snd_hda_codec_write(codec, 0x02, 0,
13055 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
13056 snd_hda_codec_write(codec, 0x03, 0,
13057 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
13058}
13059
Sasha Alexandrdef319f2009-06-16 16:00:15 -040013060/* pcm configuration: identical with ALC880 */
Kailang Yanga361d842007-06-05 12:30:55 +020013061#define alc268_pcm_analog_playback alc880_pcm_analog_playback
13062#define alc268_pcm_analog_capture alc880_pcm_analog_capture
Takashi Iwai63300792008-01-24 15:31:36 +010013063#define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
Kailang Yanga361d842007-06-05 12:30:55 +020013064#define alc268_pcm_digital_playback alc880_pcm_digital_playback
13065
13066/*
13067 * BIOS auto configuration
13068 */
13069static int alc268_parse_auto_config(struct hda_codec *codec)
13070{
13071 struct alc_spec *spec = codec->spec;
13072 int err;
13073 static hda_nid_t alc268_ignore[] = { 0 };
13074
13075 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
13076 alc268_ignore);
13077 if (err < 0)
13078 return err;
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013079 if (!spec->autocfg.line_outs) {
13080 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
13081 spec->multiout.max_channels = 2;
13082 spec->no_analog = 1;
13083 goto dig_only;
13084 }
Kailang Yanga361d842007-06-05 12:30:55 +020013085 return 0; /* can't find valid BIOS pin config */
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013086 }
Kailang Yanga361d842007-06-05 12:30:55 +020013087 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
13088 if (err < 0)
13089 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020013090 err = alc268_auto_create_input_ctls(codec, &spec->autocfg);
Kailang Yanga361d842007-06-05 12:30:55 +020013091 if (err < 0)
13092 return err;
13093
13094 spec->multiout.max_channels = 2;
13095
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013096 dig_only:
Kailang Yanga361d842007-06-05 12:30:55 +020013097 /* digital only support output */
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013098 if (spec->autocfg.dig_outs) {
Kailang Yanga361d842007-06-05 12:30:55 +020013099 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013100 spec->dig_out_type = spec->autocfg.dig_out_type[0];
13101 }
Takashi Iwai603c4012008-07-30 15:01:44 +020013102 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010013103 add_mixer(spec, spec->kctls.list);
Kailang Yanga361d842007-06-05 12:30:55 +020013104
Takashi Iwai892981f2009-03-02 08:04:35 +010013105 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d)
Takashi Iwaid88897e2008-10-31 15:01:37 +010013106 add_mixer(spec, alc268_beep_mixer);
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013107
Takashi Iwaid88897e2008-10-31 15:01:37 +010013108 add_verb(spec, alc268_volume_init_verbs);
Herton Ronaldo Krzesinski59085892009-08-11 22:33:09 -030013109 spec->num_mux_defs = 2;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020013110 spec->input_mux = &spec->private_imux[0];
Kailang Yanga361d842007-06-05 12:30:55 +020013111
Takashi Iwai776e1842007-08-29 15:07:11 +020013112 err = alc_auto_add_mic_boost(codec);
13113 if (err < 0)
13114 return err;
13115
Kailang Yang6227cdc2010-02-25 08:36:52 +010013116 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai1d955eb2009-06-29 11:33:53 +020013117
Kailang Yanga361d842007-06-05 12:30:55 +020013118 return 1;
13119}
13120
Kailang Yanga361d842007-06-05 12:30:55 +020013121#define alc268_auto_init_analog_input alc882_auto_init_analog_input
13122
13123/* init callback for auto-configuration model -- overriding the default init */
13124static void alc268_auto_init(struct hda_codec *codec)
13125{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010013126 struct alc_spec *spec = codec->spec;
Kailang Yanga361d842007-06-05 12:30:55 +020013127 alc268_auto_init_multi_out(codec);
13128 alc268_auto_init_hp_out(codec);
13129 alc268_auto_init_mono_speaker_out(codec);
13130 alc268_auto_init_analog_input(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010013131 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020013132 alc_inithook(codec);
Kailang Yanga361d842007-06-05 12:30:55 +020013133}
13134
13135/*
13136 * configuration and preset
13137 */
13138static const char *alc268_models[ALC268_MODEL_LAST] = {
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013139 [ALC267_QUANTA_IL1] = "quanta-il1",
Kailang Yanga361d842007-06-05 12:30:55 +020013140 [ALC268_3ST] = "3stack",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020013141 [ALC268_TOSHIBA] = "toshiba",
Takashi Iwaid2738092007-08-16 14:59:45 +020013142 [ALC268_ACER] = "acer",
Takashi Iwaic238b4f2008-11-05 14:57:20 +010013143 [ALC268_ACER_DMIC] = "acer-dmic",
Kailang Yang8ef355d2008-08-26 13:10:22 +020013144 [ALC268_ACER_ASPIRE_ONE] = "acer-aspire",
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013145 [ALC268_DELL] = "dell",
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013146 [ALC268_ZEPTO] = "zepto",
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013147#ifdef CONFIG_SND_DEBUG
13148 [ALC268_TEST] = "test",
13149#endif
Kailang Yanga361d842007-06-05 12:30:55 +020013150 [ALC268_AUTO] = "auto",
13151};
13152
13153static struct snd_pci_quirk alc268_cfg_tbl[] = {
Takashi Iwaia0b8f7d2008-04-22 19:39:49 +020013154 SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010013155 SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
Andy Shevchenkodafc8352008-01-25 11:53:50 +010013156 SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010013157 SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
Andy Shevchenko29a52c22008-01-24 17:29:00 +010013158 SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
Kailang Yang8ef355d2008-08-26 13:10:22 +020013159 SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
13160 ALC268_ACER_ASPIRE_ONE),
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013161 SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
Daniel T Chena1bf8082009-11-01 18:32:29 -050013162 SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
13163 "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
Takashi Iwai33d78672009-09-08 11:03:41 +020013164 /* almost compatible with toshiba but with optional digital outs;
13165 * auto-probing seems working fine
13166 */
Takashi Iwai8871e5b2009-06-02 01:02:50 +020013167 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP TX25xx series",
Takashi Iwai33d78672009-09-08 11:03:41 +020013168 ALC268_AUTO),
Kailang Yanga361d842007-06-05 12:30:55 +020013169 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
Takashi Iwai8871e5b2009-06-02 01:02:50 +020013170 SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
Tony Vroon378bd6a2008-06-04 12:08:30 +020013171 SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
Takashi Iwaib875bf32007-09-06 15:00:27 +020013172 SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013173 SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
Takashi Iwai8871e5b2009-06-02 01:02:50 +020013174 SND_PCI_QUIRK(0x1854, 0x1775, "LG R510", ALC268_DELL),
Kailang Yanga361d842007-06-05 12:30:55 +020013175 {}
13176};
13177
Takashi Iwai3abf2f32009-08-19 20:05:02 +020013178/* Toshiba laptops have no unique PCI SSID but only codec SSID */
13179static struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
13180 SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
13181 SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
13182 SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
13183 ALC268_TOSHIBA),
13184 {}
13185};
13186
Kailang Yanga361d842007-06-05 12:30:55 +020013187static struct alc_config_preset alc268_presets[] = {
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013188 [ALC267_QUANTA_IL1] = {
Takashi Iwaifdbc66262009-08-19 00:18:10 +020013189 .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
13190 alc268_capture_nosrc_mixer },
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013191 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13192 alc267_quanta_il1_verbs },
13193 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13194 .dac_nids = alc268_dac_nids,
13195 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13196 .adc_nids = alc268_adc_nids_alt,
13197 .hp_nid = 0x03,
13198 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13199 .channel_mode = alc268_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013200 .unsol_event = alc_sku_unsol_event,
13201 .setup = alc267_quanta_il1_setup,
13202 .init_hook = alc_inithook,
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013203 },
Kailang Yanga361d842007-06-05 12:30:55 +020013204 [ALC268_3ST] = {
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013205 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
13206 alc268_beep_mixer },
Kailang Yanga361d842007-06-05 12:30:55 +020013207 .init_verbs = { alc268_base_init_verbs },
13208 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13209 .dac_nids = alc268_dac_nids,
13210 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13211 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013212 .capsrc_nids = alc268_capsrc_nids,
Kailang Yanga361d842007-06-05 12:30:55 +020013213 .hp_nid = 0x03,
13214 .dig_out_nid = ALC268_DIGOUT_NID,
13215 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13216 .channel_mode = alc268_modes,
13217 .input_mux = &alc268_capture_source,
13218 },
Kailang Yangd1a991a2007-08-15 16:21:59 +020013219 [ALC268_TOSHIBA] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020013220 .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013221 alc268_beep_mixer },
Takashi Iwaid2738092007-08-16 14:59:45 +020013222 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13223 alc268_toshiba_verbs },
Kailang Yangd1a991a2007-08-15 16:21:59 +020013224 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13225 .dac_nids = alc268_dac_nids,
13226 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13227 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013228 .capsrc_nids = alc268_capsrc_nids,
Kailang Yangd1a991a2007-08-15 16:21:59 +020013229 .hp_nid = 0x03,
13230 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13231 .channel_mode = alc268_modes,
13232 .input_mux = &alc268_capture_source,
Takashi Iwaid2738092007-08-16 14:59:45 +020013233 .unsol_event = alc268_toshiba_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013234 .setup = alc268_toshiba_setup,
13235 .init_hook = alc268_toshiba_automute,
Takashi Iwaid2738092007-08-16 14:59:45 +020013236 },
13237 [ALC268_ACER] = {
Takashi Iwai432fd132009-09-30 08:13:44 +020013238 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013239 alc268_beep_mixer },
Takashi Iwaid2738092007-08-16 14:59:45 +020013240 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13241 alc268_acer_verbs },
13242 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13243 .dac_nids = alc268_dac_nids,
13244 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13245 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013246 .capsrc_nids = alc268_capsrc_nids,
Takashi Iwaid2738092007-08-16 14:59:45 +020013247 .hp_nid = 0x02,
13248 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13249 .channel_mode = alc268_modes,
Takashi Iwai0ccb5412008-03-06 16:58:35 +010013250 .input_mux = &alc268_acer_capture_source,
Takashi Iwaid2738092007-08-16 14:59:45 +020013251 .unsol_event = alc268_acer_unsol_event,
Takashi Iwai889c4392007-08-23 18:56:52 +020013252 .init_hook = alc268_acer_init_hook,
Kailang Yangd1a991a2007-08-15 16:21:59 +020013253 },
Takashi Iwaic238b4f2008-11-05 14:57:20 +010013254 [ALC268_ACER_DMIC] = {
13255 .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
13256 alc268_beep_mixer },
13257 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13258 alc268_acer_verbs },
13259 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13260 .dac_nids = alc268_dac_nids,
13261 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13262 .adc_nids = alc268_adc_nids_alt,
13263 .capsrc_nids = alc268_capsrc_nids,
13264 .hp_nid = 0x02,
13265 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13266 .channel_mode = alc268_modes,
13267 .input_mux = &alc268_acer_dmic_capture_source,
13268 .unsol_event = alc268_acer_unsol_event,
13269 .init_hook = alc268_acer_init_hook,
13270 },
Kailang Yang8ef355d2008-08-26 13:10:22 +020013271 [ALC268_ACER_ASPIRE_ONE] = {
13272 .mixers = { alc268_acer_aspire_one_mixer,
Takashi Iwai22971e32009-02-10 11:56:44 +010013273 alc268_beep_mixer,
Takashi Iwaifdbc66262009-08-19 00:18:10 +020013274 alc268_capture_nosrc_mixer },
Kailang Yang8ef355d2008-08-26 13:10:22 +020013275 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13276 alc268_acer_aspire_one_verbs },
13277 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13278 .dac_nids = alc268_dac_nids,
13279 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13280 .adc_nids = alc268_adc_nids_alt,
13281 .capsrc_nids = alc268_capsrc_nids,
13282 .hp_nid = 0x03,
13283 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13284 .channel_mode = alc268_modes,
Kailang Yang8ef355d2008-08-26 13:10:22 +020013285 .unsol_event = alc268_acer_lc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013286 .setup = alc268_acer_lc_setup,
Kailang Yang8ef355d2008-08-26 13:10:22 +020013287 .init_hook = alc268_acer_lc_init_hook,
13288 },
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013289 [ALC268_DELL] = {
Takashi Iwaifdbc66262009-08-19 00:18:10 +020013290 .mixers = { alc268_dell_mixer, alc268_beep_mixer,
13291 alc268_capture_nosrc_mixer },
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013292 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13293 alc268_dell_verbs },
13294 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13295 .dac_nids = alc268_dac_nids,
Takashi Iwaifdbc66262009-08-19 00:18:10 +020013296 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13297 .adc_nids = alc268_adc_nids_alt,
13298 .capsrc_nids = alc268_capsrc_nids,
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013299 .hp_nid = 0x02,
13300 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13301 .channel_mode = alc268_modes,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020013302 .unsol_event = alc_sku_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013303 .setup = alc268_dell_setup,
13304 .init_hook = alc_inithook,
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013305 },
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013306 [ALC268_ZEPTO] = {
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013307 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
13308 alc268_beep_mixer },
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013309 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13310 alc268_toshiba_verbs },
13311 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13312 .dac_nids = alc268_dac_nids,
13313 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13314 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013315 .capsrc_nids = alc268_capsrc_nids,
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013316 .hp_nid = 0x03,
13317 .dig_out_nid = ALC268_DIGOUT_NID,
13318 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13319 .channel_mode = alc268_modes,
13320 .input_mux = &alc268_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013321 .setup = alc268_toshiba_setup,
13322 .init_hook = alc268_toshiba_automute,
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013323 },
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013324#ifdef CONFIG_SND_DEBUG
13325 [ALC268_TEST] = {
13326 .mixers = { alc268_test_mixer, alc268_capture_mixer },
13327 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13328 alc268_volume_init_verbs },
13329 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13330 .dac_nids = alc268_dac_nids,
13331 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13332 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013333 .capsrc_nids = alc268_capsrc_nids,
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013334 .hp_nid = 0x03,
13335 .dig_out_nid = ALC268_DIGOUT_NID,
13336 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13337 .channel_mode = alc268_modes,
13338 .input_mux = &alc268_capture_source,
13339 },
13340#endif
Kailang Yanga361d842007-06-05 12:30:55 +020013341};
13342
13343static int patch_alc268(struct hda_codec *codec)
13344{
13345 struct alc_spec *spec;
13346 int board_config;
Takashi Iwai22971e32009-02-10 11:56:44 +010013347 int i, has_beep, err;
Kailang Yanga361d842007-06-05 12:30:55 +020013348
Julia Lawallef86f582009-12-19 08:18:03 +010013349 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yanga361d842007-06-05 12:30:55 +020013350 if (spec == NULL)
13351 return -ENOMEM;
13352
13353 codec->spec = spec;
13354
13355 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
13356 alc268_models,
13357 alc268_cfg_tbl);
13358
Takashi Iwai3abf2f32009-08-19 20:05:02 +020013359 if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
13360 board_config = snd_hda_check_board_codec_sid_config(codec,
Takashi Iwai50ae0aa2010-03-08 12:09:59 +010013361 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
Takashi Iwai3abf2f32009-08-19 20:05:02 +020013362
Kailang Yanga361d842007-06-05 12:30:55 +020013363 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020013364 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
13365 codec->chip_name);
Kailang Yanga361d842007-06-05 12:30:55 +020013366 board_config = ALC268_AUTO;
13367 }
13368
13369 if (board_config == ALC268_AUTO) {
13370 /* automatic parse from the BIOS config */
13371 err = alc268_parse_auto_config(codec);
13372 if (err < 0) {
13373 alc_free(codec);
13374 return err;
13375 } else if (!err) {
13376 printk(KERN_INFO
13377 "hda_codec: Cannot set up configuration "
13378 "from BIOS. Using base mode...\n");
13379 board_config = ALC268_3ST;
13380 }
13381 }
13382
13383 if (board_config != ALC268_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020013384 setup_preset(codec, &alc268_presets[board_config]);
Kailang Yanga361d842007-06-05 12:30:55 +020013385
Kailang Yanga361d842007-06-05 12:30:55 +020013386 spec->stream_analog_playback = &alc268_pcm_analog_playback;
13387 spec->stream_analog_capture = &alc268_pcm_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +010013388 spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
Kailang Yanga361d842007-06-05 12:30:55 +020013389
Kailang Yanga361d842007-06-05 12:30:55 +020013390 spec->stream_digital_playback = &alc268_pcm_digital_playback;
13391
Takashi Iwai22971e32009-02-10 11:56:44 +010013392 has_beep = 0;
13393 for (i = 0; i < spec->num_mixers; i++) {
13394 if (spec->mixers[i] == alc268_beep_mixer) {
13395 has_beep = 1;
13396 break;
13397 }
13398 }
13399
13400 if (has_beep) {
13401 err = snd_hda_attach_beep_device(codec, 0x1);
13402 if (err < 0) {
13403 alc_free(codec);
13404 return err;
13405 }
13406 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
13407 /* override the amp caps for beep generator */
13408 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013409 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
13410 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
13411 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
13412 (0 << AC_AMPCAP_MUTE_SHIFT));
Takashi Iwai22971e32009-02-10 11:56:44 +010013413 }
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013414
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013415 if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013416 /* check whether NID 0x07 is valid */
13417 unsigned int wcap = get_wcaps(codec, 0x07);
Takashi Iwai85860c02008-02-19 15:00:15 +010013418 int i;
Kailang Yanga361d842007-06-05 12:30:55 +020013419
Takashi Iwaidefb5ab2009-10-07 15:12:27 +020013420 spec->capsrc_nids = alc268_capsrc_nids;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013421 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020013422 wcap = get_wcaps_type(wcap);
Takashi Iwaifdbc66262009-08-19 00:18:10 +020013423 if (spec->auto_mic ||
13424 wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013425 spec->adc_nids = alc268_adc_nids_alt;
13426 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
Takashi Iwaidefb5ab2009-10-07 15:12:27 +020013427 if (spec->auto_mic)
13428 fixup_automic_adc(codec);
Takashi Iwaifdbc66262009-08-19 00:18:10 +020013429 if (spec->auto_mic || spec->input_mux->num_items == 1)
13430 add_mixer(spec, alc268_capture_nosrc_mixer);
13431 else
13432 add_mixer(spec, alc268_capture_alt_mixer);
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013433 } else {
13434 spec->adc_nids = alc268_adc_nids;
13435 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
Takashi Iwaid88897e2008-10-31 15:01:37 +010013436 add_mixer(spec, alc268_capture_mixer);
Kailang Yanga361d842007-06-05 12:30:55 +020013437 }
Takashi Iwai85860c02008-02-19 15:00:15 +010013438 /* set default input source */
13439 for (i = 0; i < spec->num_adc_nids; i++)
13440 snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
13441 0, AC_VERB_SET_CONNECT_SEL,
Herton Ronaldo Krzesinski59085892009-08-11 22:33:09 -030013442 i < spec->num_mux_defs ?
13443 spec->input_mux[i].items[0].index :
Takashi Iwai85860c02008-02-19 15:00:15 +010013444 spec->input_mux->items[0].index);
Kailang Yanga361d842007-06-05 12:30:55 +020013445 }
Takashi Iwai2134ea42008-01-10 16:53:55 +010013446
13447 spec->vmaster_nid = 0x02;
13448
Kailang Yanga361d842007-06-05 12:30:55 +020013449 codec->patch_ops = alc_patch_ops;
13450 if (board_config == ALC268_AUTO)
13451 spec->init_hook = alc268_auto_init;
Kailang Yangea1fb292008-08-26 12:58:38 +020013452
Kailang Yanga361d842007-06-05 12:30:55 +020013453 return 0;
13454}
13455
13456/*
Kailang Yangf6a92242007-12-13 16:52:54 +010013457 * ALC269 channel source setting (2 channel)
13458 */
13459#define ALC269_DIGOUT_NID ALC880_DIGOUT_NID
13460
13461#define alc269_dac_nids alc260_dac_nids
13462
13463static hda_nid_t alc269_adc_nids[1] = {
13464 /* ADC1 */
Kailang Yangf53281e2008-07-18 12:36:43 +020013465 0x08,
13466};
13467
Takashi Iwaie01bf502008-08-21 16:25:07 +020013468static hda_nid_t alc269_capsrc_nids[1] = {
13469 0x23,
13470};
13471
Kailang Yang84898e82010-02-04 14:16:14 +010013472static hda_nid_t alc269vb_adc_nids[1] = {
13473 /* ADC1 */
13474 0x09,
13475};
13476
13477static hda_nid_t alc269vb_capsrc_nids[1] = {
13478 0x22,
13479};
13480
Takashi Iwai66946352010-03-29 17:21:45 +020013481static hda_nid_t alc269_adc_candidates[] = {
13482 0x08, 0x09, 0x07,
13483};
Takashi Iwaie01bf502008-08-21 16:25:07 +020013484
Kailang Yangf6a92242007-12-13 16:52:54 +010013485#define alc269_modes alc260_modes
13486#define alc269_capture_source alc880_lg_lw_capture_source
13487
13488static struct snd_kcontrol_new alc269_base_mixer[] = {
13489 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13490 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13491 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
13492 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
13493 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13494 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13495 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13496 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13497 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13498 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
13499 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13500 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
13501 { } /* end */
13502};
13503
Kailang Yang60db6b52008-08-26 13:13:00 +020013504static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
13505 /* output mixer control */
13506 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13507 {
13508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13509 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010013510 .subdevice = HDA_SUBDEV_AMP_FLAG,
Kailang Yang60db6b52008-08-26 13:13:00 +020013511 .info = snd_hda_mixer_amp_switch_info,
13512 .get = snd_hda_mixer_amp_switch_get,
13513 .put = alc268_acer_master_sw_put,
13514 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
13515 },
13516 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13517 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13518 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13519 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13520 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13521 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yang60db6b52008-08-26 13:13:00 +020013522 { }
13523};
13524
Tony Vroon64154832008-11-06 15:08:49 +000013525static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
13526 /* output mixer control */
13527 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13528 {
13529 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13530 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010013531 .subdevice = HDA_SUBDEV_AMP_FLAG,
Tony Vroon64154832008-11-06 15:08:49 +000013532 .info = snd_hda_mixer_amp_switch_info,
13533 .get = snd_hda_mixer_amp_switch_get,
13534 .put = alc268_acer_master_sw_put,
13535 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
13536 },
13537 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13538 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13539 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13540 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13541 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13542 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
13543 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
13544 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
13545 HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT),
Tony Vroon64154832008-11-06 15:08:49 +000013546 { }
13547};
13548
Kailang Yang84898e82010-02-04 14:16:14 +010013549static struct snd_kcontrol_new alc269_laptop_mixer[] = {
Takashi Iwaiaa202452009-07-03 15:00:54 +020013550 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Darren Salt508f7112009-07-08 15:29:49 +010013551 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Takashi Iwaiaa202452009-07-03 15:00:54 +020013552 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Darren Salt508f7112009-07-08 15:29:49 +010013553 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yangf53281e2008-07-18 12:36:43 +020013554 { } /* end */
13555};
13556
Kailang Yang84898e82010-02-04 14:16:14 +010013557static struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
13558 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13559 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13560 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
13561 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13562 { } /* end */
13563};
13564
Kailang Yangf6a92242007-12-13 16:52:54 +010013565/* capture mixer elements */
Kailang Yang84898e82010-02-04 14:16:14 +010013566static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
13567 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
13568 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
13569 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13570 HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT),
13571 { } /* end */
13572};
13573
13574static struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
Kailang Yangf53281e2008-07-18 12:36:43 +020013575 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
13576 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
Takashi Iwai26f5df22008-11-03 17:39:46 +010013577 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13578 { } /* end */
13579};
13580
Kailang Yang84898e82010-02-04 14:16:14 +010013581static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
13582 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
13583 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
13584 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13585 HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT),
13586 { } /* end */
13587};
13588
13589static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
13590 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
13591 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
13592 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13593 { } /* end */
13594};
13595
Takashi Iwai26f5df22008-11-03 17:39:46 +010013596/* FSC amilo */
Kailang Yang84898e82010-02-04 14:16:14 +010013597#define alc269_fujitsu_mixer alc269_laptop_mixer
Kailang Yangf53281e2008-07-18 12:36:43 +020013598
Kailang Yang60db6b52008-08-26 13:13:00 +020013599static struct hda_verb alc269_quanta_fl1_verbs[] = {
13600 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13601 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13602 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13603 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13604 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13605 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13606 { }
13607};
13608
Tony Vroon64154832008-11-06 15:08:49 +000013609static struct hda_verb alc269_lifebook_verbs[] = {
13610 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13611 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
13612 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13613 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13614 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13615 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13616 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13617 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13618 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13619 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13620 { }
13621};
13622
Kailang Yang60db6b52008-08-26 13:13:00 +020013623/* toggle speaker-output according to the hp-jack state */
13624static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
13625{
13626 unsigned int present;
13627 unsigned char bits;
13628
Wu Fengguang864f92b2009-11-18 12:38:02 +080013629 present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013630 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yang60db6b52008-08-26 13:13:00 +020013631 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013632 HDA_AMP_MUTE, bits);
Kailang Yang60db6b52008-08-26 13:13:00 +020013633 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013634 HDA_AMP_MUTE, bits);
Kailang Yang60db6b52008-08-26 13:13:00 +020013635
13636 snd_hda_codec_write(codec, 0x20, 0,
13637 AC_VERB_SET_COEF_INDEX, 0x0c);
13638 snd_hda_codec_write(codec, 0x20, 0,
13639 AC_VERB_SET_PROC_COEF, 0x680);
13640
13641 snd_hda_codec_write(codec, 0x20, 0,
13642 AC_VERB_SET_COEF_INDEX, 0x0c);
13643 snd_hda_codec_write(codec, 0x20, 0,
13644 AC_VERB_SET_PROC_COEF, 0x480);
13645}
13646
Tony Vroon64154832008-11-06 15:08:49 +000013647/* toggle speaker-output according to the hp-jacks state */
13648static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
13649{
13650 unsigned int present;
13651 unsigned char bits;
13652
13653 /* Check laptop headphone socket */
Wu Fengguang864f92b2009-11-18 12:38:02 +080013654 present = snd_hda_jack_detect(codec, 0x15);
Tony Vroon64154832008-11-06 15:08:49 +000013655
13656 /* Check port replicator headphone socket */
Wu Fengguang864f92b2009-11-18 12:38:02 +080013657 present |= snd_hda_jack_detect(codec, 0x1a);
Tony Vroon64154832008-11-06 15:08:49 +000013658
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013659 bits = present ? HDA_AMP_MUTE : 0;
Tony Vroon64154832008-11-06 15:08:49 +000013660 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013661 HDA_AMP_MUTE, bits);
Tony Vroon64154832008-11-06 15:08:49 +000013662 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013663 HDA_AMP_MUTE, bits);
Tony Vroon64154832008-11-06 15:08:49 +000013664
13665 snd_hda_codec_write(codec, 0x20, 0,
13666 AC_VERB_SET_COEF_INDEX, 0x0c);
13667 snd_hda_codec_write(codec, 0x20, 0,
13668 AC_VERB_SET_PROC_COEF, 0x680);
13669
13670 snd_hda_codec_write(codec, 0x20, 0,
13671 AC_VERB_SET_COEF_INDEX, 0x0c);
13672 snd_hda_codec_write(codec, 0x20, 0,
13673 AC_VERB_SET_PROC_COEF, 0x480);
13674}
13675
Tony Vroon64154832008-11-06 15:08:49 +000013676static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
13677{
13678 unsigned int present_laptop;
13679 unsigned int present_dock;
13680
Wu Fengguang864f92b2009-11-18 12:38:02 +080013681 present_laptop = snd_hda_jack_detect(codec, 0x18);
13682 present_dock = snd_hda_jack_detect(codec, 0x1b);
Tony Vroon64154832008-11-06 15:08:49 +000013683
13684 /* Laptop mic port overrides dock mic port, design decision */
13685 if (present_dock)
13686 snd_hda_codec_write(codec, 0x23, 0,
13687 AC_VERB_SET_CONNECT_SEL, 0x3);
13688 if (present_laptop)
13689 snd_hda_codec_write(codec, 0x23, 0,
13690 AC_VERB_SET_CONNECT_SEL, 0x0);
13691 if (!present_dock && !present_laptop)
13692 snd_hda_codec_write(codec, 0x23, 0,
13693 AC_VERB_SET_CONNECT_SEL, 0x1);
13694}
13695
Kailang Yang60db6b52008-08-26 13:13:00 +020013696static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
13697 unsigned int res)
13698{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013699 switch (res >> 26) {
13700 case ALC880_HP_EVENT:
Kailang Yang60db6b52008-08-26 13:13:00 +020013701 alc269_quanta_fl1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013702 break;
13703 case ALC880_MIC_EVENT:
13704 alc_mic_automute(codec);
13705 break;
13706 }
Kailang Yang60db6b52008-08-26 13:13:00 +020013707}
13708
Tony Vroon64154832008-11-06 15:08:49 +000013709static void alc269_lifebook_unsol_event(struct hda_codec *codec,
13710 unsigned int res)
13711{
13712 if ((res >> 26) == ALC880_HP_EVENT)
13713 alc269_lifebook_speaker_automute(codec);
13714 if ((res >> 26) == ALC880_MIC_EVENT)
13715 alc269_lifebook_mic_autoswitch(codec);
13716}
13717
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013718static void alc269_quanta_fl1_setup(struct hda_codec *codec)
13719{
13720 struct alc_spec *spec = codec->spec;
Takashi Iwai20645d72010-03-02 11:14:01 +010013721 spec->autocfg.hp_pins[0] = 0x15;
13722 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013723 spec->ext_mic.pin = 0x18;
13724 spec->ext_mic.mux_idx = 0;
13725 spec->int_mic.pin = 0x19;
13726 spec->int_mic.mux_idx = 1;
13727 spec->auto_mic = 1;
13728}
13729
Kailang Yang60db6b52008-08-26 13:13:00 +020013730static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
13731{
13732 alc269_quanta_fl1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013733 alc_mic_automute(codec);
Kailang Yang60db6b52008-08-26 13:13:00 +020013734}
13735
Tony Vroon64154832008-11-06 15:08:49 +000013736static void alc269_lifebook_init_hook(struct hda_codec *codec)
13737{
13738 alc269_lifebook_speaker_automute(codec);
13739 alc269_lifebook_mic_autoswitch(codec);
13740}
13741
Kailang Yang84898e82010-02-04 14:16:14 +010013742static struct hda_verb alc269_laptop_dmic_init_verbs[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020013743 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13744 {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
13745 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
13746 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
13747 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13748 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13749 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13750 {}
13751};
13752
Kailang Yang84898e82010-02-04 14:16:14 +010013753static struct hda_verb alc269_laptop_amic_init_verbs[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020013754 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13755 {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
13756 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
13757 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
13758 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13759 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13760 {}
13761};
13762
Kailang Yang84898e82010-02-04 14:16:14 +010013763static struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
13764 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
13765 {0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
13766 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
13767 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
13768 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13769 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13770 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13771 {}
13772};
13773
13774static struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
13775 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
13776 {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
13777 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
13778 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
13779 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13780 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13781 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13782 {}
13783};
13784
Kailang Yang60db6b52008-08-26 13:13:00 +020013785/* toggle speaker-output according to the hp-jack state */
13786static void alc269_speaker_automute(struct hda_codec *codec)
13787{
Kailang Yangebb83ee2009-12-17 12:23:00 +010013788 struct alc_spec *spec = codec->spec;
13789 unsigned int nid = spec->autocfg.hp_pins[0];
Kailang Yang60db6b52008-08-26 13:13:00 +020013790 unsigned int present;
13791 unsigned char bits;
13792
Kailang Yangebb83ee2009-12-17 12:23:00 +010013793 present = snd_hda_jack_detect(codec, nid);
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013794 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yang60db6b52008-08-26 13:13:00 +020013795 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013796 HDA_AMP_MUTE, bits);
Kailang Yang60db6b52008-08-26 13:13:00 +020013797 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013798 HDA_AMP_MUTE, bits);
Kailang Yang60db6b52008-08-26 13:13:00 +020013799}
13800
Kailang Yang60db6b52008-08-26 13:13:00 +020013801/* unsolicited event for HP jack sensing */
Kailang Yang84898e82010-02-04 14:16:14 +010013802static void alc269_laptop_unsol_event(struct hda_codec *codec,
Kailang Yang60db6b52008-08-26 13:13:00 +020013803 unsigned int res)
13804{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013805 switch (res >> 26) {
13806 case ALC880_HP_EVENT:
Kailang Yang60db6b52008-08-26 13:13:00 +020013807 alc269_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013808 break;
13809 case ALC880_MIC_EVENT:
13810 alc_mic_automute(codec);
13811 break;
13812 }
Kailang Yang60db6b52008-08-26 13:13:00 +020013813}
13814
Kailang Yang226b1ec2010-04-09 11:01:20 +020013815static void alc269_laptop_amic_setup(struct hda_codec *codec)
13816{
13817 struct alc_spec *spec = codec->spec;
13818 spec->autocfg.hp_pins[0] = 0x15;
13819 spec->autocfg.speaker_pins[0] = 0x14;
13820 spec->ext_mic.pin = 0x18;
13821 spec->ext_mic.mux_idx = 0;
13822 spec->int_mic.pin = 0x19;
13823 spec->int_mic.mux_idx = 1;
13824 spec->auto_mic = 1;
13825}
13826
Kailang Yang84898e82010-02-04 14:16:14 +010013827static void alc269_laptop_dmic_setup(struct hda_codec *codec)
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013828{
13829 struct alc_spec *spec = codec->spec;
Takashi Iwai20645d72010-03-02 11:14:01 +010013830 spec->autocfg.hp_pins[0] = 0x15;
13831 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013832 spec->ext_mic.pin = 0x18;
13833 spec->ext_mic.mux_idx = 0;
13834 spec->int_mic.pin = 0x12;
13835 spec->int_mic.mux_idx = 5;
13836 spec->auto_mic = 1;
13837}
13838
Kailang Yang226b1ec2010-04-09 11:01:20 +020013839static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
Kailang Yang84898e82010-02-04 14:16:14 +010013840{
13841 struct alc_spec *spec = codec->spec;
Kailang Yang226b1ec2010-04-09 11:01:20 +020013842 spec->autocfg.hp_pins[0] = 0x21;
Takashi Iwai20645d72010-03-02 11:14:01 +010013843 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013844 spec->ext_mic.pin = 0x18;
13845 spec->ext_mic.mux_idx = 0;
13846 spec->int_mic.pin = 0x19;
13847 spec->int_mic.mux_idx = 1;
13848 spec->auto_mic = 1;
13849}
13850
Kailang Yang226b1ec2010-04-09 11:01:20 +020013851static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
13852{
13853 struct alc_spec *spec = codec->spec;
13854 spec->autocfg.hp_pins[0] = 0x21;
13855 spec->autocfg.speaker_pins[0] = 0x14;
13856 spec->ext_mic.pin = 0x18;
13857 spec->ext_mic.mux_idx = 0;
13858 spec->int_mic.pin = 0x12;
13859 spec->int_mic.mux_idx = 6;
13860 spec->auto_mic = 1;
13861}
13862
Kailang Yang84898e82010-02-04 14:16:14 +010013863static void alc269_laptop_inithook(struct hda_codec *codec)
Kailang Yang60db6b52008-08-26 13:13:00 +020013864{
13865 alc269_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013866 alc_mic_automute(codec);
Kailang Yang60db6b52008-08-26 13:13:00 +020013867}
13868
Kailang Yangf6a92242007-12-13 16:52:54 +010013869/*
13870 * generic initialization of ADC, input mixers and output mixers
13871 */
13872static struct hda_verb alc269_init_verbs[] = {
13873 /*
13874 * Unmute ADC0 and set the default input to mic-in
13875 */
Kailang Yang84898e82010-02-04 14:16:14 +010013876 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangf6a92242007-12-13 16:52:54 +010013877
13878 /*
Kailang Yang84898e82010-02-04 14:16:14 +010013879 * Set up output mixers (0x02 - 0x03)
Kailang Yangf6a92242007-12-13 16:52:54 +010013880 */
13881 /* set vol=0 to output mixers */
13882 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13883 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13884
13885 /* set up input amps for analog loopback */
13886 /* Amp Indices: DAC = 0, mixer = 1 */
13887 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13888 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13889 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13890 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13891 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13892 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13893
13894 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13895 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13896 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13897 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13898 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13899 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13900 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13901
13902 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13903 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangf6a92242007-12-13 16:52:54 +010013904
Kailang Yang84898e82010-02-04 14:16:14 +010013905 /* FIXME: use Mux-type input source selection */
Kailang Yangf6a92242007-12-13 16:52:54 +010013906 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
13907 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
Kailang Yang84898e82010-02-04 14:16:14 +010013908 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangf6a92242007-12-13 16:52:54 +010013909
13910 /* set EAPD */
13911 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
Kailang Yang84898e82010-02-04 14:16:14 +010013912 { }
13913};
13914
13915static struct hda_verb alc269vb_init_verbs[] = {
13916 /*
13917 * Unmute ADC0 and set the default input to mic-in
13918 */
13919 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13920
13921 /*
13922 * Set up output mixers (0x02 - 0x03)
13923 */
13924 /* set vol=0 to output mixers */
13925 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13926 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13927
13928 /* set up input amps for analog loopback */
13929 /* Amp Indices: DAC = 0, mixer = 1 */
13930 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13931 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13932 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13933 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13934 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13935 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13936
13937 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13938 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13939 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13940 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13941 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13942 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13943 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13944
13945 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13946 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13947
13948 /* FIXME: use Mux-type input source selection */
13949 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
13950 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
13951 {0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
13952
13953 /* set EAPD */
13954 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
Kailang Yangf6a92242007-12-13 16:52:54 +010013955 { }
13956};
13957
Takashi Iwai9d0b71b2009-08-24 14:10:30 +020013958#define alc269_auto_create_multi_out_ctls \
13959 alc268_auto_create_multi_out_ctls
Takashi Iwai05f5f472009-08-25 13:10:18 +020013960#define alc269_auto_create_input_ctls \
13961 alc268_auto_create_input_ctls
Kailang Yangf6a92242007-12-13 16:52:54 +010013962
13963#ifdef CONFIG_SND_HDA_POWER_SAVE
13964#define alc269_loopbacks alc880_loopbacks
13965#endif
13966
Sasha Alexandrdef319f2009-06-16 16:00:15 -040013967/* pcm configuration: identical with ALC880 */
Kailang Yangf6a92242007-12-13 16:52:54 +010013968#define alc269_pcm_analog_playback alc880_pcm_analog_playback
13969#define alc269_pcm_analog_capture alc880_pcm_analog_capture
13970#define alc269_pcm_digital_playback alc880_pcm_digital_playback
13971#define alc269_pcm_digital_capture alc880_pcm_digital_capture
13972
Takashi Iwaif03d3112009-03-05 14:18:16 +010013973static struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
13974 .substreams = 1,
13975 .channels_min = 2,
13976 .channels_max = 8,
13977 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
13978 /* NID is set in alc_build_pcms */
13979 .ops = {
13980 .open = alc880_playback_pcm_open,
13981 .prepare = alc880_playback_pcm_prepare,
13982 .cleanup = alc880_playback_pcm_cleanup
13983 },
13984};
13985
13986static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
13987 .substreams = 1,
13988 .channels_min = 2,
13989 .channels_max = 2,
13990 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
13991 /* NID is set in alc_build_pcms */
13992};
13993
Kailang Yangf6a92242007-12-13 16:52:54 +010013994/*
13995 * BIOS auto configuration
13996 */
13997static int alc269_parse_auto_config(struct hda_codec *codec)
13998{
13999 struct alc_spec *spec = codec->spec;
Takashi Iwaicfb9fb52009-02-06 17:34:03 +010014000 int err;
Kailang Yangf6a92242007-12-13 16:52:54 +010014001 static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
14002
14003 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
14004 alc269_ignore);
14005 if (err < 0)
14006 return err;
14007
14008 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
14009 if (err < 0)
14010 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020014011 err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
Kailang Yangf6a92242007-12-13 16:52:54 +010014012 if (err < 0)
14013 return err;
14014
14015 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
14016
Takashi Iwai0852d7a2009-02-11 11:35:15 +010014017 if (spec->autocfg.dig_outs)
Kailang Yangf6a92242007-12-13 16:52:54 +010014018 spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
14019
Takashi Iwai603c4012008-07-30 15:01:44 +020014020 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010014021 add_mixer(spec, spec->kctls.list);
Kailang Yangf6a92242007-12-13 16:52:54 +010014022
Kailang Yang84898e82010-02-04 14:16:14 +010014023 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) {
14024 add_verb(spec, alc269vb_init_verbs);
Kailang Yang6227cdc2010-02-25 08:36:52 +010014025 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
Kailang Yang84898e82010-02-04 14:16:14 +010014026 } else {
14027 add_verb(spec, alc269_init_verbs);
Kailang Yang6227cdc2010-02-25 08:36:52 +010014028 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Kailang Yang84898e82010-02-04 14:16:14 +010014029 }
14030
Kailang Yangf6a92242007-12-13 16:52:54 +010014031 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020014032 spec->input_mux = &spec->private_imux[0];
Takashi Iwai66946352010-03-29 17:21:45 +020014033 fillup_priv_adc_nids(codec, alc269_adc_candidates,
14034 sizeof(alc269_adc_candidates));
14035
Takashi Iwaie01bf502008-08-21 16:25:07 +020014036 /* set default input source */
Takashi Iwai66946352010-03-29 17:21:45 +020014037 snd_hda_codec_write_cache(codec, spec->capsrc_nids[0],
Takashi Iwaie01bf502008-08-21 16:25:07 +020014038 0, AC_VERB_SET_CONNECT_SEL,
14039 spec->input_mux->items[0].index);
Kailang Yangf6a92242007-12-13 16:52:54 +010014040
14041 err = alc_auto_add_mic_boost(codec);
14042 if (err < 0)
14043 return err;
14044
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010014045 if (!spec->cap_mixer && !spec->no_analog)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020014046 set_capture_mixer(codec);
Kailang Yangf53281e2008-07-18 12:36:43 +020014047
Kailang Yangf6a92242007-12-13 16:52:54 +010014048 return 1;
14049}
14050
Takashi Iwaie9af4f32009-08-29 23:23:08 +020014051#define alc269_auto_init_multi_out alc268_auto_init_multi_out
14052#define alc269_auto_init_hp_out alc268_auto_init_hp_out
Kailang Yangf6a92242007-12-13 16:52:54 +010014053#define alc269_auto_init_analog_input alc882_auto_init_analog_input
14054
14055
14056/* init callback for auto-configuration model -- overriding the default init */
14057static void alc269_auto_init(struct hda_codec *codec)
14058{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010014059 struct alc_spec *spec = codec->spec;
Kailang Yangf6a92242007-12-13 16:52:54 +010014060 alc269_auto_init_multi_out(codec);
14061 alc269_auto_init_hp_out(codec);
14062 alc269_auto_init_analog_input(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010014063 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020014064 alc_inithook(codec);
Kailang Yangf6a92242007-12-13 16:52:54 +010014065}
14066
14067/*
14068 * configuration and preset
14069 */
14070static const char *alc269_models[ALC269_MODEL_LAST] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020014071 [ALC269_BASIC] = "basic",
Takashi Iwai2922c9a2008-08-27 18:12:42 +020014072 [ALC269_QUANTA_FL1] = "quanta",
Kailang Yang84898e82010-02-04 14:16:14 +010014073 [ALC269_AMIC] = "laptop-amic",
14074 [ALC269_DMIC] = "laptop-dmic",
Tony Vroon64154832008-11-06 15:08:49 +000014075 [ALC269_FUJITSU] = "fujitsu",
Takashi Iwai3d3792c2009-09-11 07:50:47 +020014076 [ALC269_LIFEBOOK] = "lifebook",
14077 [ALC269_AUTO] = "auto",
Kailang Yangf6a92242007-12-13 16:52:54 +010014078};
14079
14080static struct snd_pci_quirk alc269_cfg_tbl[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020014081 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
Kailang Yangf53281e2008-07-18 12:36:43 +020014082 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
Kailang Yang84898e82010-02-04 14:16:14 +010014083 ALC269_AMIC),
14084 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
14085 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
14086 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
14087 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
14088 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
14089 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
14090 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
14091 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
14092 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
14093 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_AMIC),
14094 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
14095 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
14096 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
14097 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
14098 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
14099 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
14100 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
14101 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
14102 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
14103 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
14104 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
14105 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
14106 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
14107 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
14108 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
14109 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
14110 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
14111 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
14112 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
14113 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
14114 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
14115 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
14116 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
14117 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
14118 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
14119 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
Kailang Yangf53281e2008-07-18 12:36:43 +020014120 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
Kailang Yang84898e82010-02-04 14:16:14 +010014121 ALC269_DMIC),
Kailang Yang60db6b52008-08-26 13:13:00 +020014122 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
Kailang Yang84898e82010-02-04 14:16:14 +010014123 ALC269_DMIC),
14124 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
14125 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
Kailang Yang61c2d2b2010-02-25 08:49:06 +010014126 SND_PCI_QUIRK(0x104d, 0x9071, "SONY XTB", ALC269_DMIC),
Tony Vroon64154832008-11-06 15:08:49 +000014127 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
Kailang Yang61c2d2b2010-02-25 08:49:06 +010014128 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
14129 SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
14130 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC),
14131 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC),
14132 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC),
14133 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC),
Kailang Yangf6a92242007-12-13 16:52:54 +010014134 {}
14135};
14136
14137static struct alc_config_preset alc269_presets[] = {
14138 [ALC269_BASIC] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010014139 .mixers = { alc269_base_mixer },
Kailang Yangf6a92242007-12-13 16:52:54 +010014140 .init_verbs = { alc269_init_verbs },
14141 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14142 .dac_nids = alc269_dac_nids,
14143 .hp_nid = 0x03,
14144 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14145 .channel_mode = alc269_modes,
14146 .input_mux = &alc269_capture_source,
14147 },
Kailang Yang60db6b52008-08-26 13:13:00 +020014148 [ALC269_QUANTA_FL1] = {
14149 .mixers = { alc269_quanta_fl1_mixer },
14150 .init_verbs = { alc269_init_verbs, alc269_quanta_fl1_verbs },
14151 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14152 .dac_nids = alc269_dac_nids,
14153 .hp_nid = 0x03,
14154 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14155 .channel_mode = alc269_modes,
14156 .input_mux = &alc269_capture_source,
14157 .unsol_event = alc269_quanta_fl1_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014158 .setup = alc269_quanta_fl1_setup,
Kailang Yang60db6b52008-08-26 13:13:00 +020014159 .init_hook = alc269_quanta_fl1_init_hook,
14160 },
Kailang Yang84898e82010-02-04 14:16:14 +010014161 [ALC269_AMIC] = {
14162 .mixers = { alc269_laptop_mixer },
14163 .cap_mixer = alc269_laptop_analog_capture_mixer,
Kailang Yangf53281e2008-07-18 12:36:43 +020014164 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010014165 alc269_laptop_amic_init_verbs },
Kailang Yangf53281e2008-07-18 12:36:43 +020014166 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14167 .dac_nids = alc269_dac_nids,
14168 .hp_nid = 0x03,
14169 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14170 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010014171 .unsol_event = alc269_laptop_unsol_event,
14172 .setup = alc269_laptop_amic_setup,
14173 .init_hook = alc269_laptop_inithook,
Kailang Yangf53281e2008-07-18 12:36:43 +020014174 },
Kailang Yang84898e82010-02-04 14:16:14 +010014175 [ALC269_DMIC] = {
14176 .mixers = { alc269_laptop_mixer },
14177 .cap_mixer = alc269_laptop_digital_capture_mixer,
Kailang Yangf53281e2008-07-18 12:36:43 +020014178 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010014179 alc269_laptop_dmic_init_verbs },
Kailang Yangf53281e2008-07-18 12:36:43 +020014180 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14181 .dac_nids = alc269_dac_nids,
14182 .hp_nid = 0x03,
14183 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14184 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010014185 .unsol_event = alc269_laptop_unsol_event,
14186 .setup = alc269_laptop_dmic_setup,
14187 .init_hook = alc269_laptop_inithook,
14188 },
14189 [ALC269VB_AMIC] = {
14190 .mixers = { alc269vb_laptop_mixer },
14191 .cap_mixer = alc269vb_laptop_analog_capture_mixer,
14192 .init_verbs = { alc269vb_init_verbs,
14193 alc269vb_laptop_amic_init_verbs },
14194 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14195 .dac_nids = alc269_dac_nids,
14196 .hp_nid = 0x03,
14197 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14198 .channel_mode = alc269_modes,
14199 .unsol_event = alc269_laptop_unsol_event,
Kailang Yang226b1ec2010-04-09 11:01:20 +020014200 .setup = alc269vb_laptop_amic_setup,
Kailang Yang84898e82010-02-04 14:16:14 +010014201 .init_hook = alc269_laptop_inithook,
14202 },
14203 [ALC269VB_DMIC] = {
14204 .mixers = { alc269vb_laptop_mixer },
14205 .cap_mixer = alc269vb_laptop_digital_capture_mixer,
14206 .init_verbs = { alc269vb_init_verbs,
14207 alc269vb_laptop_dmic_init_verbs },
14208 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14209 .dac_nids = alc269_dac_nids,
14210 .hp_nid = 0x03,
14211 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14212 .channel_mode = alc269_modes,
14213 .unsol_event = alc269_laptop_unsol_event,
14214 .setup = alc269vb_laptop_dmic_setup,
14215 .init_hook = alc269_laptop_inithook,
Kailang Yangf53281e2008-07-18 12:36:43 +020014216 },
Takashi Iwai26f5df22008-11-03 17:39:46 +010014217 [ALC269_FUJITSU] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010014218 .mixers = { alc269_fujitsu_mixer },
Kailang Yang84898e82010-02-04 14:16:14 +010014219 .cap_mixer = alc269_laptop_digital_capture_mixer,
Takashi Iwai26f5df22008-11-03 17:39:46 +010014220 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010014221 alc269_laptop_dmic_init_verbs },
Takashi Iwai26f5df22008-11-03 17:39:46 +010014222 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14223 .dac_nids = alc269_dac_nids,
14224 .hp_nid = 0x03,
14225 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14226 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010014227 .unsol_event = alc269_laptop_unsol_event,
14228 .setup = alc269_laptop_dmic_setup,
14229 .init_hook = alc269_laptop_inithook,
Takashi Iwai26f5df22008-11-03 17:39:46 +010014230 },
Tony Vroon64154832008-11-06 15:08:49 +000014231 [ALC269_LIFEBOOK] = {
14232 .mixers = { alc269_lifebook_mixer },
14233 .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
14234 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14235 .dac_nids = alc269_dac_nids,
14236 .hp_nid = 0x03,
14237 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14238 .channel_mode = alc269_modes,
14239 .input_mux = &alc269_capture_source,
14240 .unsol_event = alc269_lifebook_unsol_event,
14241 .init_hook = alc269_lifebook_init_hook,
14242 },
Kailang Yangf6a92242007-12-13 16:52:54 +010014243};
14244
14245static int patch_alc269(struct hda_codec *codec)
14246{
14247 struct alc_spec *spec;
14248 int board_config;
14249 int err;
Kailang Yang84898e82010-02-04 14:16:14 +010014250 int is_alc269vb = 0;
Kailang Yangf6a92242007-12-13 16:52:54 +010014251
14252 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
14253 if (spec == NULL)
14254 return -ENOMEM;
14255
14256 codec->spec = spec;
14257
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +020014258 alc_fix_pll_init(codec, 0x20, 0x04, 15);
14259
Kailang Yang274693f2009-12-03 10:07:50 +010014260 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
14261 kfree(codec->chip_name);
14262 codec->chip_name = kstrdup("ALC259", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010014263 if (!codec->chip_name) {
14264 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010014265 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010014266 }
Kailang Yang84898e82010-02-04 14:16:14 +010014267 is_alc269vb = 1;
Kailang Yang274693f2009-12-03 10:07:50 +010014268 }
14269
Kailang Yangf6a92242007-12-13 16:52:54 +010014270 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
14271 alc269_models,
14272 alc269_cfg_tbl);
14273
14274 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020014275 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
14276 codec->chip_name);
Kailang Yangf6a92242007-12-13 16:52:54 +010014277 board_config = ALC269_AUTO;
14278 }
14279
14280 if (board_config == ALC269_AUTO) {
14281 /* automatic parse from the BIOS config */
14282 err = alc269_parse_auto_config(codec);
14283 if (err < 0) {
14284 alc_free(codec);
14285 return err;
14286 } else if (!err) {
14287 printk(KERN_INFO
14288 "hda_codec: Cannot set up configuration "
14289 "from BIOS. Using base mode...\n");
14290 board_config = ALC269_BASIC;
14291 }
14292 }
14293
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090014294 err = snd_hda_attach_beep_device(codec, 0x1);
14295 if (err < 0) {
14296 alc_free(codec);
14297 return err;
14298 }
14299
Kailang Yangf6a92242007-12-13 16:52:54 +010014300 if (board_config != ALC269_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020014301 setup_preset(codec, &alc269_presets[board_config]);
Kailang Yangf6a92242007-12-13 16:52:54 +010014302
Kailang Yang84898e82010-02-04 14:16:14 +010014303 if (board_config == ALC269_QUANTA_FL1) {
Takashi Iwaif03d3112009-03-05 14:18:16 +010014304 /* Due to a hardware problem on Lenovo Ideadpad, we need to
14305 * fix the sample rate of analog I/O to 44.1kHz
14306 */
14307 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
14308 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
14309 } else {
14310 spec->stream_analog_playback = &alc269_pcm_analog_playback;
14311 spec->stream_analog_capture = &alc269_pcm_analog_capture;
14312 }
Kailang Yangf6a92242007-12-13 16:52:54 +010014313 spec->stream_digital_playback = &alc269_pcm_digital_playback;
14314 spec->stream_digital_capture = &alc269_pcm_digital_capture;
14315
Takashi Iwai66946352010-03-29 17:21:45 +020014316 if (!spec->adc_nids) { /* wasn't filled automatically? use default */
14317 if (!is_alc269vb) {
14318 spec->adc_nids = alc269_adc_nids;
14319 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
14320 spec->capsrc_nids = alc269_capsrc_nids;
14321 } else {
14322 spec->adc_nids = alc269vb_adc_nids;
14323 spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
14324 spec->capsrc_nids = alc269vb_capsrc_nids;
14325 }
Kailang Yang84898e82010-02-04 14:16:14 +010014326 }
14327
Takashi Iwaif9e336f2008-10-31 16:37:07 +010014328 if (!spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020014329 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010014330 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Kailang Yangf6a92242007-12-13 16:52:54 +010014331
Takashi Iwai100d5eb2009-08-10 11:55:51 +020014332 spec->vmaster_nid = 0x02;
14333
Kailang Yangf6a92242007-12-13 16:52:54 +010014334 codec->patch_ops = alc_patch_ops;
14335 if (board_config == ALC269_AUTO)
14336 spec->init_hook = alc269_auto_init;
14337#ifdef CONFIG_SND_HDA_POWER_SAVE
14338 if (!spec->loopback.amplist)
14339 spec->loopback.amplist = alc269_loopbacks;
14340#endif
14341
14342 return 0;
14343}
14344
14345/*
Kailang Yangdf694da2005-12-05 19:42:22 +010014346 * ALC861 channel source setting (2/6 channel selection for 3-stack)
14347 */
14348
14349/*
14350 * set the path ways for 2 channel output
14351 * need to set the codec line out and mic 1 pin widgets to inputs
14352 */
14353static struct hda_verb alc861_threestack_ch2_init[] = {
14354 /* set pin widget 1Ah (line in) for input */
14355 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014356 /* set pin widget 18h (mic1/2) for input, for mic also enable
14357 * the vref
14358 */
Kailang Yangdf694da2005-12-05 19:42:22 +010014359 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14360
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014361 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
14362#if 0
14363 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14364 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
14365#endif
Kailang Yangdf694da2005-12-05 19:42:22 +010014366 { } /* end */
14367};
14368/*
14369 * 6ch mode
14370 * need to set the codec line out and mic 1 pin widgets to outputs
14371 */
14372static struct hda_verb alc861_threestack_ch6_init[] = {
14373 /* set pin widget 1Ah (line in) for output (Back Surround)*/
14374 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14375 /* set pin widget 18h (mic1) for output (CLFE)*/
14376 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14377
14378 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014379 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010014380
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014381 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
14382#if 0
14383 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14384 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
14385#endif
Kailang Yangdf694da2005-12-05 19:42:22 +010014386 { } /* end */
14387};
14388
14389static struct hda_channel_mode alc861_threestack_modes[2] = {
14390 { 2, alc861_threestack_ch2_init },
14391 { 6, alc861_threestack_ch6_init },
14392};
Takashi Iwai22309c32006-08-09 16:57:28 +020014393/* Set mic1 as input and unmute the mixer */
14394static struct hda_verb alc861_uniwill_m31_ch2_init[] = {
14395 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14396 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14397 { } /* end */
14398};
14399/* Set mic1 as output and mute mixer */
14400static struct hda_verb alc861_uniwill_m31_ch4_init[] = {
14401 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14402 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14403 { } /* end */
14404};
14405
14406static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
14407 { 2, alc861_uniwill_m31_ch2_init },
14408 { 4, alc861_uniwill_m31_ch4_init },
14409};
Kailang Yangdf694da2005-12-05 19:42:22 +010014410
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014411/* Set mic1 and line-in as input and unmute the mixer */
14412static struct hda_verb alc861_asus_ch2_init[] = {
14413 /* set pin widget 1Ah (line in) for input */
14414 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014415 /* set pin widget 18h (mic1/2) for input, for mic also enable
14416 * the vref
14417 */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014418 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14419
14420 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
14421#if 0
14422 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14423 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
14424#endif
14425 { } /* end */
14426};
14427/* Set mic1 nad line-in as output and mute mixer */
14428static struct hda_verb alc861_asus_ch6_init[] = {
14429 /* set pin widget 1Ah (line in) for output (Back Surround)*/
14430 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14431 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
14432 /* set pin widget 18h (mic1) for output (CLFE)*/
14433 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14434 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
14435 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
14436 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
14437
14438 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
14439#if 0
14440 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14441 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
14442#endif
14443 { } /* end */
14444};
14445
14446static struct hda_channel_mode alc861_asus_modes[2] = {
14447 { 2, alc861_asus_ch2_init },
14448 { 6, alc861_asus_ch6_init },
14449};
14450
Kailang Yangdf694da2005-12-05 19:42:22 +010014451/* patch-ALC861 */
14452
14453static struct snd_kcontrol_new alc861_base_mixer[] = {
14454 /* output mixer control */
14455 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14456 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14457 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14458 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14459 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
14460
14461 /*Input mixer control */
14462 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14463 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14464 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14465 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14466 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14467 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14468 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14469 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14470 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14471 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014472
Kailang Yangdf694da2005-12-05 19:42:22 +010014473 { } /* end */
14474};
14475
14476static struct snd_kcontrol_new alc861_3ST_mixer[] = {
14477 /* output mixer control */
14478 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14479 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14480 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14481 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14482 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
14483
14484 /* Input mixer control */
14485 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14486 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14487 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14488 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14489 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14490 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14491 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14492 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14493 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14494 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014495
Kailang Yangdf694da2005-12-05 19:42:22 +010014496 {
14497 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14498 .name = "Channel Mode",
14499 .info = alc_ch_mode_info,
14500 .get = alc_ch_mode_get,
14501 .put = alc_ch_mode_put,
14502 .private_value = ARRAY_SIZE(alc861_threestack_modes),
14503 },
14504 { } /* end */
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014505};
14506
Takashi Iwaid1d985f2006-11-23 19:27:12 +010014507static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014508 /* output mixer control */
14509 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14510 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14511 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
Kailang Yangea1fb292008-08-26 12:58:38 +020014512
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014513 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014514};
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014515
Takashi Iwai22309c32006-08-09 16:57:28 +020014516static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
14517 /* output mixer control */
14518 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14519 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14520 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14521 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14522 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
14523
14524 /* Input mixer control */
14525 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14526 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14527 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14528 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14529 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14530 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14531 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14532 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14533 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14534 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014535
Takashi Iwai22309c32006-08-09 16:57:28 +020014536 {
14537 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14538 .name = "Channel Mode",
14539 .info = alc_ch_mode_info,
14540 .get = alc_ch_mode_get,
14541 .put = alc_ch_mode_put,
14542 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
14543 },
14544 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014545};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014546
14547static struct snd_kcontrol_new alc861_asus_mixer[] = {
14548 /* output mixer control */
14549 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14550 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14551 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14552 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14553 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
14554
14555 /* Input mixer control */
14556 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14557 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
14558 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14559 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14560 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14561 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14562 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14563 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14564 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014565 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
14566
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014567 {
14568 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14569 .name = "Channel Mode",
14570 .info = alc_ch_mode_info,
14571 .get = alc_ch_mode_get,
14572 .put = alc_ch_mode_put,
14573 .private_value = ARRAY_SIZE(alc861_asus_modes),
14574 },
14575 { }
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014576};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014577
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014578/* additional mixer */
Takashi Iwaid1d985f2006-11-23 19:27:12 +010014579static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014580 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14581 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014582 { }
14583};
14584
Kailang Yangdf694da2005-12-05 19:42:22 +010014585/*
14586 * generic initialization of ADC, input mixers and output mixers
14587 */
14588static struct hda_verb alc861_base_init_verbs[] = {
14589 /*
14590 * Unmute ADC0 and set the default input to mic-in
14591 */
14592 /* port-A for surround (rear panel) */
14593 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14594 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
14595 /* port-B for mic-in (rear panel) with vref */
14596 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14597 /* port-C for line-in (rear panel) */
14598 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14599 /* port-D for Front */
14600 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14601 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
14602 /* port-E for HP out (front panel) */
14603 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
14604 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010014605 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010014606 /* port-F for mic-in (front panel) with vref */
14607 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14608 /* port-G for CLFE (rear panel) */
14609 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14610 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
14611 /* port-H for side (rear panel) */
14612 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14613 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
14614 /* CD-in */
14615 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14616 /* route front mic to ADC1*/
14617 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
14618 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014619
Kailang Yangdf694da2005-12-05 19:42:22 +010014620 /* Unmute DAC0~3 & spdif out*/
14621 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14622 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14623 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14624 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14625 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020014626
Kailang Yangdf694da2005-12-05 19:42:22 +010014627 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14628 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14629 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14630 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14631 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014632
Kailang Yangdf694da2005-12-05 19:42:22 +010014633 /* Unmute Stereo Mixer 15 */
14634 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14635 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14636 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014637 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Kailang Yangdf694da2005-12-05 19:42:22 +010014638
14639 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14640 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14641 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14642 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14643 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14644 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14645 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14646 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014647 /* hp used DAC 3 (Front) */
14648 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014649 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14650
14651 { }
14652};
14653
14654static struct hda_verb alc861_threestack_init_verbs[] = {
14655 /*
14656 * Unmute ADC0 and set the default input to mic-in
14657 */
14658 /* port-A for surround (rear panel) */
14659 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14660 /* port-B for mic-in (rear panel) with vref */
14661 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14662 /* port-C for line-in (rear panel) */
14663 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14664 /* port-D for Front */
14665 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14666 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
14667 /* port-E for HP out (front panel) */
14668 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
14669 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010014670 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010014671 /* port-F for mic-in (front panel) with vref */
14672 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14673 /* port-G for CLFE (rear panel) */
14674 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14675 /* port-H for side (rear panel) */
14676 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14677 /* CD-in */
14678 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14679 /* route front mic to ADC1*/
14680 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
14681 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14682 /* Unmute DAC0~3 & spdif out*/
14683 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14684 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14685 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14686 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14687 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020014688
Kailang Yangdf694da2005-12-05 19:42:22 +010014689 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14690 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14691 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14692 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14693 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014694
Kailang Yangdf694da2005-12-05 19:42:22 +010014695 /* Unmute Stereo Mixer 15 */
14696 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14697 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14698 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014699 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Kailang Yangdf694da2005-12-05 19:42:22 +010014700
14701 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14702 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14703 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14704 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14705 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14706 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14707 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14708 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014709 /* hp used DAC 3 (Front) */
14710 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014711 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14712 { }
14713};
Takashi Iwai22309c32006-08-09 16:57:28 +020014714
14715static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
14716 /*
14717 * Unmute ADC0 and set the default input to mic-in
14718 */
14719 /* port-A for surround (rear panel) */
14720 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14721 /* port-B for mic-in (rear panel) with vref */
14722 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14723 /* port-C for line-in (rear panel) */
14724 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14725 /* port-D for Front */
14726 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14727 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
14728 /* port-E for HP out (front panel) */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014729 /* this has to be set to VREF80 */
14730 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
Takashi Iwai22309c32006-08-09 16:57:28 +020014731 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010014732 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Takashi Iwai22309c32006-08-09 16:57:28 +020014733 /* port-F for mic-in (front panel) with vref */
14734 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14735 /* port-G for CLFE (rear panel) */
14736 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14737 /* port-H for side (rear panel) */
14738 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14739 /* CD-in */
14740 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14741 /* route front mic to ADC1*/
14742 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
14743 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14744 /* Unmute DAC0~3 & spdif out*/
14745 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14746 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14747 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14748 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14749 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020014750
Takashi Iwai22309c32006-08-09 16:57:28 +020014751 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14752 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14753 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14754 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14755 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014756
Takashi Iwai22309c32006-08-09 16:57:28 +020014757 /* Unmute Stereo Mixer 15 */
14758 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14759 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14760 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014761 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Takashi Iwai22309c32006-08-09 16:57:28 +020014762
14763 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14764 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14765 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14766 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14767 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14768 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14769 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14770 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014771 /* hp used DAC 3 (Front) */
14772 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Takashi Iwai22309c32006-08-09 16:57:28 +020014773 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14774 { }
14775};
14776
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014777static struct hda_verb alc861_asus_init_verbs[] = {
14778 /*
14779 * Unmute ADC0 and set the default input to mic-in
14780 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014781 /* port-A for surround (rear panel)
14782 * according to codec#0 this is the HP jack
14783 */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014784 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
14785 /* route front PCM to HP */
14786 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
14787 /* port-B for mic-in (rear panel) with vref */
14788 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14789 /* port-C for line-in (rear panel) */
14790 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14791 /* port-D for Front */
14792 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14793 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
14794 /* port-E for HP out (front panel) */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014795 /* this has to be set to VREF80 */
14796 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014797 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010014798 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014799 /* port-F for mic-in (front panel) with vref */
14800 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14801 /* port-G for CLFE (rear panel) */
14802 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14803 /* port-H for side (rear panel) */
14804 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14805 /* CD-in */
14806 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14807 /* route front mic to ADC1*/
14808 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
14809 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14810 /* Unmute DAC0~3 & spdif out*/
14811 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14812 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14813 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14814 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14815 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14816 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14817 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14818 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14819 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14820 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014821
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014822 /* Unmute Stereo Mixer 15 */
14823 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14824 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14825 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014826 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014827
14828 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14829 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14830 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14831 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14832 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14833 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14834 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14835 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014836 /* hp used DAC 3 (Front) */
14837 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014838 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14839 { }
14840};
14841
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014842/* additional init verbs for ASUS laptops */
14843static struct hda_verb alc861_asus_laptop_init_verbs[] = {
14844 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
14845 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
14846 { }
14847};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014848
Kailang Yangdf694da2005-12-05 19:42:22 +010014849/*
14850 * generic initialization of ADC, input mixers and output mixers
14851 */
14852static struct hda_verb alc861_auto_init_verbs[] = {
14853 /*
14854 * Unmute ADC0 and set the default input to mic-in
14855 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014856 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
Kailang Yangdf694da2005-12-05 19:42:22 +010014857 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014858
Kailang Yangdf694da2005-12-05 19:42:22 +010014859 /* Unmute DAC0~3 & spdif out*/
14860 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14861 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14862 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14863 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14864 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020014865
Kailang Yangdf694da2005-12-05 19:42:22 +010014866 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14867 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14868 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14869 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14870 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014871
Kailang Yangdf694da2005-12-05 19:42:22 +010014872 /* Unmute Stereo Mixer 15 */
14873 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14874 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14875 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14876 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
14877
Takashi Iwai1c209302009-07-22 15:17:45 +020014878 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14879 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
14880 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14881 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
14882 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14883 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
14884 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14885 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014886
14887 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14888 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai1c209302009-07-22 15:17:45 +020014889 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
14890 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014891 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14892 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai1c209302009-07-22 15:17:45 +020014893 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
14894 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014895
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014896 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */
Kailang Yangdf694da2005-12-05 19:42:22 +010014897
14898 { }
14899};
14900
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014901static struct hda_verb alc861_toshiba_init_verbs[] = {
14902 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014903
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014904 { }
14905};
14906
14907/* toggle speaker-output according to the hp-jack state */
14908static void alc861_toshiba_automute(struct hda_codec *codec)
14909{
Wu Fengguang864f92b2009-11-18 12:38:02 +080014910 unsigned int present = snd_hda_jack_detect(codec, 0x0f);
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014911
Takashi Iwai47fd8302007-08-10 17:11:07 +020014912 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
14913 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
14914 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
14915 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014916}
14917
14918static void alc861_toshiba_unsol_event(struct hda_codec *codec,
14919 unsigned int res)
14920{
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014921 if ((res >> 26) == ALC880_HP_EVENT)
14922 alc861_toshiba_automute(codec);
14923}
14924
Sasha Alexandrdef319f2009-06-16 16:00:15 -040014925/* pcm configuration: identical with ALC880 */
Kailang Yangdf694da2005-12-05 19:42:22 +010014926#define alc861_pcm_analog_playback alc880_pcm_analog_playback
14927#define alc861_pcm_analog_capture alc880_pcm_analog_capture
14928#define alc861_pcm_digital_playback alc880_pcm_digital_playback
14929#define alc861_pcm_digital_capture alc880_pcm_digital_capture
14930
14931
14932#define ALC861_DIGOUT_NID 0x07
14933
14934static struct hda_channel_mode alc861_8ch_modes[1] = {
14935 { 8, NULL }
14936};
14937
14938static hda_nid_t alc861_dac_nids[4] = {
14939 /* front, surround, clfe, side */
14940 0x03, 0x06, 0x05, 0x04
14941};
14942
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014943static hda_nid_t alc660_dac_nids[3] = {
14944 /* front, clfe, surround */
14945 0x03, 0x05, 0x06
14946};
14947
Kailang Yangdf694da2005-12-05 19:42:22 +010014948static hda_nid_t alc861_adc_nids[1] = {
14949 /* ADC0-2 */
14950 0x08,
14951};
14952
14953static struct hda_input_mux alc861_capture_source = {
14954 .num_items = 5,
14955 .items = {
14956 { "Mic", 0x0 },
14957 { "Front Mic", 0x3 },
14958 { "Line", 0x1 },
14959 { "CD", 0x4 },
14960 { "Mixer", 0x5 },
14961 },
14962};
14963
Takashi Iwai1c209302009-07-22 15:17:45 +020014964static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
14965{
14966 struct alc_spec *spec = codec->spec;
14967 hda_nid_t mix, srcs[5];
14968 int i, j, num;
14969
14970 if (snd_hda_get_connections(codec, pin, &mix, 1) != 1)
14971 return 0;
14972 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
14973 if (num < 0)
14974 return 0;
14975 for (i = 0; i < num; i++) {
14976 unsigned int type;
Takashi Iwaia22d5432009-07-27 12:54:26 +020014977 type = get_wcaps_type(get_wcaps(codec, srcs[i]));
Takashi Iwai1c209302009-07-22 15:17:45 +020014978 if (type != AC_WID_AUD_OUT)
14979 continue;
14980 for (j = 0; j < spec->multiout.num_dacs; j++)
14981 if (spec->multiout.dac_nids[j] == srcs[i])
14982 break;
14983 if (j >= spec->multiout.num_dacs)
14984 return srcs[i];
14985 }
14986 return 0;
14987}
14988
Kailang Yangdf694da2005-12-05 19:42:22 +010014989/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai1c209302009-07-22 15:17:45 +020014990static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014991 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010014992{
Takashi Iwai1c209302009-07-22 15:17:45 +020014993 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010014994 int i;
Takashi Iwai1c209302009-07-22 15:17:45 +020014995 hda_nid_t nid, dac;
Kailang Yangdf694da2005-12-05 19:42:22 +010014996
14997 spec->multiout.dac_nids = spec->private_dac_nids;
14998 for (i = 0; i < cfg->line_outs; i++) {
14999 nid = cfg->line_out_pins[i];
Takashi Iwai1c209302009-07-22 15:17:45 +020015000 dac = alc861_look_for_dac(codec, nid);
15001 if (!dac)
15002 continue;
15003 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
Kailang Yangdf694da2005-12-05 19:42:22 +010015004 }
Kailang Yangdf694da2005-12-05 19:42:22 +010015005 return 0;
15006}
15007
Takashi Iwai1c209302009-07-22 15:17:45 +020015008static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
15009 hda_nid_t nid, unsigned int chs)
Kailang Yangdf694da2005-12-05 19:42:22 +010015010{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020015011 return add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai1c209302009-07-22 15:17:45 +020015012 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
15013}
15014
15015/* add playback controls from the parsed DAC table */
15016static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
15017 const struct auto_pin_cfg *cfg)
15018{
15019 struct alc_spec *spec = codec->spec;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015020 static const char *chname[4] = {
15021 "Front", "Surround", NULL /*CLFE*/, "Side"
15022 };
Kailang Yangdf694da2005-12-05 19:42:22 +010015023 hda_nid_t nid;
Takashi Iwai1c209302009-07-22 15:17:45 +020015024 int i, err;
15025
15026 if (cfg->line_outs == 1) {
15027 const char *pfx = NULL;
15028 if (!cfg->hp_outs)
15029 pfx = "Master";
15030 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
15031 pfx = "Speaker";
15032 if (pfx) {
15033 nid = spec->multiout.dac_nids[0];
15034 return alc861_create_out_sw(codec, pfx, nid, 3);
15035 }
15036 }
Kailang Yangdf694da2005-12-05 19:42:22 +010015037
15038 for (i = 0; i < cfg->line_outs; i++) {
15039 nid = spec->multiout.dac_nids[i];
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015040 if (!nid)
Kailang Yangdf694da2005-12-05 19:42:22 +010015041 continue;
Takashi Iwai1c209302009-07-22 15:17:45 +020015042 if (i == 2) {
Kailang Yangdf694da2005-12-05 19:42:22 +010015043 /* Center/LFE */
Takashi Iwai1c209302009-07-22 15:17:45 +020015044 err = alc861_create_out_sw(codec, "Center", nid, 1);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015045 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015046 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020015047 err = alc861_create_out_sw(codec, "LFE", nid, 2);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015048 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015049 return err;
15050 } else {
Takashi Iwai1c209302009-07-22 15:17:45 +020015051 err = alc861_create_out_sw(codec, chname[i], nid, 3);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015052 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015053 return err;
15054 }
15055 }
15056 return 0;
15057}
15058
Takashi Iwai1c209302009-07-22 15:17:45 +020015059static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
Kailang Yangdf694da2005-12-05 19:42:22 +010015060{
Takashi Iwai1c209302009-07-22 15:17:45 +020015061 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015062 int err;
15063 hda_nid_t nid;
15064
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015065 if (!pin)
Kailang Yangdf694da2005-12-05 19:42:22 +010015066 return 0;
15067
15068 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
Takashi Iwai1c209302009-07-22 15:17:45 +020015069 nid = alc861_look_for_dac(codec, pin);
15070 if (nid) {
15071 err = alc861_create_out_sw(codec, "Headphone", nid, 3);
15072 if (err < 0)
15073 return err;
15074 spec->multiout.hp_nid = nid;
15075 }
Kailang Yangdf694da2005-12-05 19:42:22 +010015076 }
15077 return 0;
15078}
15079
15080/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020015081static int alc861_auto_create_input_ctls(struct hda_codec *codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015082 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010015083{
Takashi Iwai05f5f472009-08-25 13:10:18 +020015084 return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x08, 0);
Kailang Yangdf694da2005-12-05 19:42:22 +010015085}
15086
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015087static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
15088 hda_nid_t nid,
Takashi Iwai1c209302009-07-22 15:17:45 +020015089 int pin_type, hda_nid_t dac)
Kailang Yangdf694da2005-12-05 19:42:22 +010015090{
Takashi Iwai1c209302009-07-22 15:17:45 +020015091 hda_nid_t mix, srcs[5];
15092 int i, num;
15093
Jacek Luczak564c5be2008-05-03 18:41:23 +020015094 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
15095 pin_type);
Takashi Iwai1c209302009-07-22 15:17:45 +020015096 snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Jacek Luczak564c5be2008-05-03 18:41:23 +020015097 AMP_OUT_UNMUTE);
Takashi Iwai1c209302009-07-22 15:17:45 +020015098 if (snd_hda_get_connections(codec, nid, &mix, 1) != 1)
15099 return;
15100 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
15101 if (num < 0)
15102 return;
15103 for (i = 0; i < num; i++) {
15104 unsigned int mute;
15105 if (srcs[i] == dac || srcs[i] == 0x15)
15106 mute = AMP_IN_UNMUTE(i);
15107 else
15108 mute = AMP_IN_MUTE(i);
15109 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
15110 mute);
15111 }
Kailang Yangdf694da2005-12-05 19:42:22 +010015112}
15113
15114static void alc861_auto_init_multi_out(struct hda_codec *codec)
15115{
15116 struct alc_spec *spec = codec->spec;
15117 int i;
15118
15119 for (i = 0; i < spec->autocfg.line_outs; i++) {
15120 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020015121 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangdf694da2005-12-05 19:42:22 +010015122 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020015123 alc861_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015124 spec->multiout.dac_nids[i]);
Kailang Yangdf694da2005-12-05 19:42:22 +010015125 }
15126}
15127
15128static void alc861_auto_init_hp_out(struct hda_codec *codec)
15129{
15130 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015131
Takashi Iwai15870f02009-10-05 08:25:13 +020015132 if (spec->autocfg.hp_outs)
15133 alc861_auto_set_output_and_unmute(codec,
15134 spec->autocfg.hp_pins[0],
15135 PIN_HP,
Takashi Iwai1c209302009-07-22 15:17:45 +020015136 spec->multiout.hp_nid);
Takashi Iwai15870f02009-10-05 08:25:13 +020015137 if (spec->autocfg.speaker_outs)
15138 alc861_auto_set_output_and_unmute(codec,
15139 spec->autocfg.speaker_pins[0],
15140 PIN_OUT,
Takashi Iwai1c209302009-07-22 15:17:45 +020015141 spec->multiout.dac_nids[0]);
Kailang Yangdf694da2005-12-05 19:42:22 +010015142}
15143
15144static void alc861_auto_init_analog_input(struct hda_codec *codec)
15145{
15146 struct alc_spec *spec = codec->spec;
15147 int i;
15148
15149 for (i = 0; i < AUTO_PIN_LAST; i++) {
15150 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai23f0c042009-02-26 13:03:58 +010015151 if (nid >= 0x0c && nid <= 0x11)
15152 alc_set_input_pin(codec, nid, i);
Kailang Yangdf694da2005-12-05 19:42:22 +010015153 }
15154}
15155
15156/* parse the BIOS configuration and set up the alc_spec */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015157/* return 1 if successful, 0 if the proper config is not found,
15158 * or a negative error code
15159 */
Kailang Yangdf694da2005-12-05 19:42:22 +010015160static int alc861_parse_auto_config(struct hda_codec *codec)
15161{
15162 struct alc_spec *spec = codec->spec;
15163 int err;
15164 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
15165
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015166 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
15167 alc861_ignore);
15168 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015169 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015170 if (!spec->autocfg.line_outs)
Kailang Yangdf694da2005-12-05 19:42:22 +010015171 return 0; /* can't find valid BIOS pin config */
15172
Takashi Iwai1c209302009-07-22 15:17:45 +020015173 err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015174 if (err < 0)
15175 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020015176 err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015177 if (err < 0)
15178 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020015179 err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015180 if (err < 0)
15181 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020015182 err = alc861_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015183 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015184 return err;
15185
15186 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
15187
Takashi Iwai0852d7a2009-02-11 11:35:15 +010015188 if (spec->autocfg.dig_outs)
Kailang Yangdf694da2005-12-05 19:42:22 +010015189 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
15190
Takashi Iwai603c4012008-07-30 15:01:44 +020015191 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010015192 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +010015193
Takashi Iwaid88897e2008-10-31 15:01:37 +010015194 add_verb(spec, alc861_auto_init_verbs);
Kailang Yangdf694da2005-12-05 19:42:22 +010015195
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +020015196 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020015197 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +010015198
15199 spec->adc_nids = alc861_adc_nids;
15200 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
Takashi Iwaib59bdf32009-08-11 09:47:30 +020015201 set_capture_mixer(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010015202
Kailang Yang6227cdc2010-02-25 08:36:52 +010015203 alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020015204
Kailang Yangdf694da2005-12-05 19:42:22 +010015205 return 1;
15206}
15207
Takashi Iwaiae6b8132006-03-03 16:47:17 +010015208/* additional initialization for auto-configuration model */
15209static void alc861_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +010015210{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010015211 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015212 alc861_auto_init_multi_out(codec);
15213 alc861_auto_init_hp_out(codec);
15214 alc861_auto_init_analog_input(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010015215 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020015216 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010015217}
15218
Takashi Iwaicb53c622007-08-10 17:21:45 +020015219#ifdef CONFIG_SND_HDA_POWER_SAVE
15220static struct hda_amp_list alc861_loopbacks[] = {
15221 { 0x15, HDA_INPUT, 0 },
15222 { 0x15, HDA_INPUT, 1 },
15223 { 0x15, HDA_INPUT, 2 },
15224 { 0x15, HDA_INPUT, 3 },
15225 { } /* end */
15226};
15227#endif
15228
Kailang Yangdf694da2005-12-05 19:42:22 +010015229
15230/*
15231 * configuration and preset
15232 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015233static const char *alc861_models[ALC861_MODEL_LAST] = {
15234 [ALC861_3ST] = "3stack",
15235 [ALC660_3ST] = "3stack-660",
15236 [ALC861_3ST_DIG] = "3stack-dig",
15237 [ALC861_6ST_DIG] = "6stack-dig",
15238 [ALC861_UNIWILL_M31] = "uniwill-m31",
15239 [ALC861_TOSHIBA] = "toshiba",
15240 [ALC861_ASUS] = "asus",
15241 [ALC861_ASUS_LAPTOP] = "asus-laptop",
15242 [ALC861_AUTO] = "auto",
15243};
15244
15245static struct snd_pci_quirk alc861_cfg_tbl[] = {
Takashi Iwai687a47b2007-01-10 11:25:58 +010015246 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015247 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
15248 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
15249 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015250 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
Kailang Yang83c34212007-07-05 11:43:05 +020015251 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
Tobin Davisad5e7732007-01-08 10:57:32 +010015252 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
Takashi Iwai341d4eb2007-07-09 17:53:18 +020015253 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
15254 * Any other models that need this preset?
15255 */
15256 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
Claudio Matsuokaef64adb2007-07-14 00:26:16 +020015257 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
15258 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015259 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
15260 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
15261 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
15262 /* FIXME: the below seems conflict */
15263 /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
15264 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
15265 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
Kailang Yangdf694da2005-12-05 19:42:22 +010015266 {}
15267};
15268
15269static struct alc_config_preset alc861_presets[] = {
15270 [ALC861_3ST] = {
15271 .mixers = { alc861_3ST_mixer },
15272 .init_verbs = { alc861_threestack_init_verbs },
15273 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15274 .dac_nids = alc861_dac_nids,
15275 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15276 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015277 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +010015278 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15279 .adc_nids = alc861_adc_nids,
15280 .input_mux = &alc861_capture_source,
15281 },
15282 [ALC861_3ST_DIG] = {
15283 .mixers = { alc861_base_mixer },
15284 .init_verbs = { alc861_threestack_init_verbs },
15285 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15286 .dac_nids = alc861_dac_nids,
15287 .dig_out_nid = ALC861_DIGOUT_NID,
15288 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15289 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015290 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +010015291 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15292 .adc_nids = alc861_adc_nids,
15293 .input_mux = &alc861_capture_source,
15294 },
15295 [ALC861_6ST_DIG] = {
15296 .mixers = { alc861_base_mixer },
15297 .init_verbs = { alc861_base_init_verbs },
15298 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15299 .dac_nids = alc861_dac_nids,
15300 .dig_out_nid = ALC861_DIGOUT_NID,
15301 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
15302 .channel_mode = alc861_8ch_modes,
15303 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15304 .adc_nids = alc861_adc_nids,
15305 .input_mux = &alc861_capture_source,
15306 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015307 [ALC660_3ST] = {
15308 .mixers = { alc861_3ST_mixer },
15309 .init_verbs = { alc861_threestack_init_verbs },
15310 .num_dacs = ARRAY_SIZE(alc660_dac_nids),
15311 .dac_nids = alc660_dac_nids,
15312 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15313 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015314 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015315 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15316 .adc_nids = alc861_adc_nids,
15317 .input_mux = &alc861_capture_source,
15318 },
Takashi Iwai22309c32006-08-09 16:57:28 +020015319 [ALC861_UNIWILL_M31] = {
15320 .mixers = { alc861_uniwill_m31_mixer },
15321 .init_verbs = { alc861_uniwill_m31_init_verbs },
15322 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15323 .dac_nids = alc861_dac_nids,
15324 .dig_out_nid = ALC861_DIGOUT_NID,
15325 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
15326 .channel_mode = alc861_uniwill_m31_modes,
15327 .need_dac_fix = 1,
15328 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15329 .adc_nids = alc861_adc_nids,
15330 .input_mux = &alc861_capture_source,
15331 },
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015332 [ALC861_TOSHIBA] = {
15333 .mixers = { alc861_toshiba_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015334 .init_verbs = { alc861_base_init_verbs,
15335 alc861_toshiba_init_verbs },
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015336 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15337 .dac_nids = alc861_dac_nids,
15338 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
15339 .channel_mode = alc883_3ST_2ch_modes,
15340 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15341 .adc_nids = alc861_adc_nids,
15342 .input_mux = &alc861_capture_source,
15343 .unsol_event = alc861_toshiba_unsol_event,
15344 .init_hook = alc861_toshiba_automute,
15345 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015346 [ALC861_ASUS] = {
15347 .mixers = { alc861_asus_mixer },
15348 .init_verbs = { alc861_asus_init_verbs },
15349 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15350 .dac_nids = alc861_dac_nids,
15351 .dig_out_nid = ALC861_DIGOUT_NID,
15352 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
15353 .channel_mode = alc861_asus_modes,
15354 .need_dac_fix = 1,
15355 .hp_nid = 0x06,
15356 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15357 .adc_nids = alc861_adc_nids,
15358 .input_mux = &alc861_capture_source,
15359 },
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010015360 [ALC861_ASUS_LAPTOP] = {
15361 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
15362 .init_verbs = { alc861_asus_init_verbs,
15363 alc861_asus_laptop_init_verbs },
15364 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15365 .dac_nids = alc861_dac_nids,
15366 .dig_out_nid = ALC861_DIGOUT_NID,
15367 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
15368 .channel_mode = alc883_3ST_2ch_modes,
15369 .need_dac_fix = 1,
15370 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15371 .adc_nids = alc861_adc_nids,
15372 .input_mux = &alc861_capture_source,
15373 },
15374};
Kailang Yangdf694da2005-12-05 19:42:22 +010015375
Takashi Iwaicfc9b062009-12-01 12:19:37 +010015376/* Pin config fixes */
15377enum {
15378 PINFIX_FSC_AMILO_PI1505,
15379};
15380
15381static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = {
15382 { 0x0b, 0x0221101f }, /* HP */
15383 { 0x0f, 0x90170310 }, /* speaker */
15384 { }
15385};
15386
15387static const struct alc_fixup alc861_fixups[] = {
15388 [PINFIX_FSC_AMILO_PI1505] = {
15389 .pins = alc861_fsc_amilo_pi1505_pinfix
15390 },
15391};
15392
15393static struct snd_pci_quirk alc861_fixup_tbl[] = {
15394 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
15395 {}
15396};
Kailang Yangdf694da2005-12-05 19:42:22 +010015397
15398static int patch_alc861(struct hda_codec *codec)
15399{
15400 struct alc_spec *spec;
15401 int board_config;
15402 int err;
15403
Robert P. J. Daydc041e02006-12-19 14:44:15 +010015404 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yangdf694da2005-12-05 19:42:22 +010015405 if (spec == NULL)
15406 return -ENOMEM;
15407
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015408 codec->spec = spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015409
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015410 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
15411 alc861_models,
15412 alc861_cfg_tbl);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015413
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015414 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020015415 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
15416 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +010015417 board_config = ALC861_AUTO;
15418 }
15419
Takashi Iwaicfc9b062009-12-01 12:19:37 +010015420 alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups);
15421
Kailang Yangdf694da2005-12-05 19:42:22 +010015422 if (board_config == ALC861_AUTO) {
15423 /* automatic parse from the BIOS config */
15424 err = alc861_parse_auto_config(codec);
15425 if (err < 0) {
15426 alc_free(codec);
15427 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015428 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015429 printk(KERN_INFO
15430 "hda_codec: Cannot set up configuration "
15431 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +010015432 board_config = ALC861_3ST_DIG;
15433 }
15434 }
15435
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090015436 err = snd_hda_attach_beep_device(codec, 0x23);
15437 if (err < 0) {
15438 alc_free(codec);
15439 return err;
15440 }
15441
Kailang Yangdf694da2005-12-05 19:42:22 +010015442 if (board_config != ALC861_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020015443 setup_preset(codec, &alc861_presets[board_config]);
Kailang Yangdf694da2005-12-05 19:42:22 +010015444
Kailang Yangdf694da2005-12-05 19:42:22 +010015445 spec->stream_analog_playback = &alc861_pcm_analog_playback;
15446 spec->stream_analog_capture = &alc861_pcm_analog_capture;
15447
Kailang Yangdf694da2005-12-05 19:42:22 +010015448 spec->stream_digital_playback = &alc861_pcm_digital_playback;
15449 spec->stream_digital_capture = &alc861_pcm_digital_capture;
15450
Takashi Iwaic7a8eb12010-01-14 12:39:02 +010015451 if (!spec->cap_mixer)
15452 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010015453 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
15454
Takashi Iwai2134ea42008-01-10 16:53:55 +010015455 spec->vmaster_nid = 0x03;
15456
Kailang Yangdf694da2005-12-05 19:42:22 +010015457 codec->patch_ops = alc_patch_ops;
Daniel T Chenc97259d2009-12-27 18:52:08 -050015458 if (board_config == ALC861_AUTO) {
Takashi Iwaiae6b8132006-03-03 16:47:17 +010015459 spec->init_hook = alc861_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020015460#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -050015461 spec->power_hook = alc_power_eapd;
15462#endif
15463 }
15464#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaicb53c622007-08-10 17:21:45 +020015465 if (!spec->loopback.amplist)
15466 spec->loopback.amplist = alc861_loopbacks;
15467#endif
Kailang Yangea1fb292008-08-26 12:58:38 +020015468
Kailang Yangdf694da2005-12-05 19:42:22 +010015469 return 0;
15470}
15471
15472/*
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015473 * ALC861-VD support
15474 *
15475 * Based on ALC882
15476 *
15477 * In addition, an independent DAC
15478 */
15479#define ALC861VD_DIGOUT_NID 0x06
15480
15481static hda_nid_t alc861vd_dac_nids[4] = {
15482 /* front, surr, clfe, side surr */
15483 0x02, 0x03, 0x04, 0x05
15484};
15485
15486/* dac_nids for ALC660vd are in a different order - according to
15487 * Realtek's driver.
Sasha Alexandrdef319f2009-06-16 16:00:15 -040015488 * This should probably result in a different mixer for 6stack models
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015489 * of ALC660vd codecs, but for now there is only 3stack mixer
15490 * - and it is the same as in 861vd.
15491 * adc_nids in ALC660vd are (is) the same as in 861vd
15492 */
15493static hda_nid_t alc660vd_dac_nids[3] = {
15494 /* front, rear, clfe, rear_surr */
15495 0x02, 0x04, 0x03
15496};
15497
15498static hda_nid_t alc861vd_adc_nids[1] = {
15499 /* ADC0 */
15500 0x09,
15501};
15502
Takashi Iwaie1406342008-02-11 18:32:32 +010015503static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
15504
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015505/* input MUX */
15506/* FIXME: should be a matrix-type input source selection */
15507static struct hda_input_mux alc861vd_capture_source = {
15508 .num_items = 4,
15509 .items = {
15510 { "Mic", 0x0 },
15511 { "Front Mic", 0x1 },
15512 { "Line", 0x2 },
15513 { "CD", 0x4 },
15514 },
15515};
15516
Kailang Yang272a5272007-05-14 11:00:38 +020015517static struct hda_input_mux alc861vd_dallas_capture_source = {
Tobin Davisb419f342008-03-07 11:57:51 +010015518 .num_items = 2,
Kailang Yang272a5272007-05-14 11:00:38 +020015519 .items = {
Tobin Davisb419f342008-03-07 11:57:51 +010015520 { "Ext Mic", 0x0 },
15521 { "Int Mic", 0x1 },
Kailang Yang272a5272007-05-14 11:00:38 +020015522 },
15523};
15524
Kailang Yangd1a991a2007-08-15 16:21:59 +020015525static struct hda_input_mux alc861vd_hp_capture_source = {
15526 .num_items = 2,
15527 .items = {
15528 { "Front Mic", 0x0 },
15529 { "ATAPI Mic", 0x1 },
15530 },
15531};
15532
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015533/*
15534 * 2ch mode
15535 */
15536static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
15537 { 2, NULL }
15538};
15539
15540/*
15541 * 6ch mode
15542 */
15543static struct hda_verb alc861vd_6stack_ch6_init[] = {
15544 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15545 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15546 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15547 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15548 { } /* end */
15549};
15550
15551/*
15552 * 8ch mode
15553 */
15554static struct hda_verb alc861vd_6stack_ch8_init[] = {
15555 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15556 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15557 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15558 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15559 { } /* end */
15560};
15561
15562static struct hda_channel_mode alc861vd_6stack_modes[2] = {
15563 { 6, alc861vd_6stack_ch6_init },
15564 { 8, alc861vd_6stack_ch8_init },
15565};
15566
15567static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
15568 {
15569 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15570 .name = "Channel Mode",
15571 .info = alc_ch_mode_info,
15572 .get = alc_ch_mode_get,
15573 .put = alc_ch_mode_put,
15574 },
15575 { } /* end */
15576};
15577
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015578/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
15579 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
15580 */
15581static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
15582 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15583 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
15584
15585 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
15586 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
15587
15588 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
15589 HDA_OUTPUT),
15590 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
15591 HDA_OUTPUT),
15592 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
15593 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
15594
15595 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
15596 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
15597
15598 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
15599
15600 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
15601 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15602 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15603
15604 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
15605 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15606 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
15607
15608 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
15609 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
15610
15611 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
15612 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
15613
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015614 { } /* end */
15615};
15616
15617static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
15618 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15619 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
15620
15621 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
15622
15623 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
15624 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15625 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15626
15627 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
15628 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15629 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
15630
15631 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
15632 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
15633
15634 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
15635 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
15636
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015637 { } /* end */
15638};
15639
Kailang Yangbdd148a2007-05-08 15:19:08 +020015640static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
15641 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15642 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
15643 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
15644
15645 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
15646
15647 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
15648 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15649 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15650
15651 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
15652 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15653 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
15654
15655 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
15656 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
15657
15658 { } /* end */
15659};
15660
Tobin Davisb419f342008-03-07 11:57:51 +010015661/* Pin assignment: Speaker=0x14, HP = 0x15,
15662 * Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
Kailang Yang272a5272007-05-14 11:00:38 +020015663 */
15664static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
Tobin Davisb419f342008-03-07 11:57:51 +010015665 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15666 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +020015667 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
15668 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
Tobin Davisb419f342008-03-07 11:57:51 +010015669 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
15670 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15671 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15672 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
15673 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15674 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +020015675 { } /* end */
15676};
15677
Kailang Yangd1a991a2007-08-15 16:21:59 +020015678/* Pin assignment: Speaker=0x14, Line-out = 0x15,
15679 * Front Mic=0x18, ATAPI Mic = 0x19,
15680 */
15681static struct snd_kcontrol_new alc861vd_hp_mixer[] = {
15682 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15683 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
15684 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
15685 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
15686 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15687 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15688 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15689 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangea1fb292008-08-26 12:58:38 +020015690
Kailang Yangd1a991a2007-08-15 16:21:59 +020015691 { } /* end */
15692};
15693
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015694/*
15695 * generic initialization of ADC, input mixers and output mixers
15696 */
15697static struct hda_verb alc861vd_volume_init_verbs[] = {
15698 /*
15699 * Unmute ADC0 and set the default input to mic-in
15700 */
15701 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
15702 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15703
15704 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
15705 * the analog-loopback mixer widget
15706 */
15707 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020015708 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15709 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15710 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15711 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
15712 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015713
15714 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
Kailang Yangbdd148a2007-05-08 15:19:08 +020015715 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15716 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15717 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015718 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015719
15720 /*
15721 * Set up output mixers (0x02 - 0x05)
15722 */
15723 /* set vol=0 to output mixers */
15724 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15725 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15726 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15727 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15728
15729 /* set up input amps for analog loopback */
15730 /* Amp Indices: DAC = 0, mixer = 1 */
15731 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15732 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15733 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15734 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15735 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15736 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15737 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15738 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15739
15740 { }
15741};
15742
15743/*
15744 * 3-stack pin configuration:
15745 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
15746 */
15747static struct hda_verb alc861vd_3stack_init_verbs[] = {
15748 /*
15749 * Set pin mode and muting
15750 */
15751 /* set front pin widgets 0x14 for output */
15752 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15753 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15754 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
15755
15756 /* Mic (rear) pin: input vref at 80% */
15757 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
15758 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15759 /* Front Mic pin: input vref at 80% */
15760 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
15761 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15762 /* Line In pin: input */
15763 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15764 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15765 /* Line-2 In: Headphone output (output 0 - 0x0c) */
15766 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
15767 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15768 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
15769 /* CD pin widget for input */
15770 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15771
15772 { }
15773};
15774
15775/*
15776 * 6-stack pin configuration:
15777 */
15778static struct hda_verb alc861vd_6stack_init_verbs[] = {
15779 /*
15780 * Set pin mode and muting
15781 */
15782 /* set front pin widgets 0x14 for output */
15783 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15784 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15785 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
15786
15787 /* Rear Pin: output 1 (0x0d) */
15788 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15789 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15790 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
15791 /* CLFE Pin: output 2 (0x0e) */
15792 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15793 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15794 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
15795 /* Side Pin: output 3 (0x0f) */
15796 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15797 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15798 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
15799
15800 /* Mic (rear) pin: input vref at 80% */
15801 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
15802 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15803 /* Front Mic pin: input vref at 80% */
15804 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
15805 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15806 /* Line In pin: input */
15807 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15808 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15809 /* Line-2 In: Headphone output (output 0 - 0x0c) */
15810 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
15811 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15812 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
15813 /* CD pin widget for input */
15814 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15815
15816 { }
15817};
15818
Kailang Yangbdd148a2007-05-08 15:19:08 +020015819static struct hda_verb alc861vd_eapd_verbs[] = {
15820 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
15821 { }
15822};
15823
Kailang Yangf9423e72008-05-27 12:32:25 +020015824static struct hda_verb alc660vd_eapd_verbs[] = {
15825 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
15826 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
15827 { }
15828};
15829
Kailang Yangbdd148a2007-05-08 15:19:08 +020015830static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
15831 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15832 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15833 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
15834 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Kailang Yangea1fb292008-08-26 12:58:38 +020015835 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
Kailang Yangbdd148a2007-05-08 15:19:08 +020015836 {}
15837};
15838
Kailang Yangbdd148a2007-05-08 15:19:08 +020015839static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
15840{
15841 unsigned int present;
15842 unsigned char bits;
15843
Wu Fengguang864f92b2009-11-18 12:38:02 +080015844 present = snd_hda_jack_detect(codec, 0x18);
Takashi Iwai47fd8302007-08-10 17:11:07 +020015845 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080015846
Takashi Iwai47fd8302007-08-10 17:11:07 +020015847 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
15848 HDA_AMP_MUTE, bits);
Kailang Yangbdd148a2007-05-08 15:19:08 +020015849}
15850
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015851static void alc861vd_lenovo_setup(struct hda_codec *codec)
Kailang Yangbdd148a2007-05-08 15:19:08 +020015852{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015853 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015854 spec->autocfg.hp_pins[0] = 0x1b;
15855 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015856}
15857
15858static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
15859{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015860 alc_automute_amp(codec);
Kailang Yangbdd148a2007-05-08 15:19:08 +020015861 alc861vd_lenovo_mic_automute(codec);
15862}
15863
15864static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
15865 unsigned int res)
15866{
15867 switch (res >> 26) {
Kailang Yangbdd148a2007-05-08 15:19:08 +020015868 case ALC880_MIC_EVENT:
15869 alc861vd_lenovo_mic_automute(codec);
15870 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015871 default:
15872 alc_automute_amp_unsol_event(codec, res);
15873 break;
Kailang Yangbdd148a2007-05-08 15:19:08 +020015874 }
15875}
15876
Kailang Yang272a5272007-05-14 11:00:38 +020015877static struct hda_verb alc861vd_dallas_verbs[] = {
15878 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15879 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15880 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15881 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15882
15883 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15884 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15885 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15886 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15887 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15888 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15889 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15890 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015891
Kailang Yang272a5272007-05-14 11:00:38 +020015892 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15893 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15894 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15895 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15896 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15897 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15898 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15899 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15900
15901 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
15902 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15903 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
15904 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15905 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15906 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15907 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15908 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15909
15910 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15911 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
15912 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15913 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
15914
15915 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015916 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yang272a5272007-05-14 11:00:38 +020015917 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
15918
15919 { } /* end */
15920};
15921
15922/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015923static void alc861vd_dallas_setup(struct hda_codec *codec)
Kailang Yang272a5272007-05-14 11:00:38 +020015924{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015925 struct alc_spec *spec = codec->spec;
Kailang Yang272a5272007-05-14 11:00:38 +020015926
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015927 spec->autocfg.hp_pins[0] = 0x15;
15928 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang272a5272007-05-14 11:00:38 +020015929}
15930
Takashi Iwaicb53c622007-08-10 17:21:45 +020015931#ifdef CONFIG_SND_HDA_POWER_SAVE
15932#define alc861vd_loopbacks alc880_loopbacks
15933#endif
15934
Sasha Alexandrdef319f2009-06-16 16:00:15 -040015935/* pcm configuration: identical with ALC880 */
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015936#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
15937#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
15938#define alc861vd_pcm_digital_playback alc880_pcm_digital_playback
15939#define alc861vd_pcm_digital_capture alc880_pcm_digital_capture
15940
15941/*
15942 * configuration and preset
15943 */
15944static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
15945 [ALC660VD_3ST] = "3stack-660",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020015946 [ALC660VD_3ST_DIG] = "3stack-660-digout",
Takashi Iwai13c94742008-11-05 08:06:08 +010015947 [ALC660VD_ASUS_V1S] = "asus-v1s",
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015948 [ALC861VD_3ST] = "3stack",
15949 [ALC861VD_3ST_DIG] = "3stack-digout",
15950 [ALC861VD_6ST_DIG] = "6stack-digout",
Kailang Yangbdd148a2007-05-08 15:19:08 +020015951 [ALC861VD_LENOVO] = "lenovo",
Kailang Yang272a5272007-05-14 11:00:38 +020015952 [ALC861VD_DALLAS] = "dallas",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020015953 [ALC861VD_HP] = "hp",
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015954 [ALC861VD_AUTO] = "auto",
15955};
15956
15957static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015958 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
15959 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
Takashi Iwai07e038b2007-02-15 18:23:41 +010015960 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020015961 /*SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),*/ /* auto */
Takashi Iwai13c94742008-11-05 08:06:08 +010015962 SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
Mike Crash6963f842007-06-25 12:12:51 +020015963 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015964 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015965 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
Takashi Iwai38baf5a2007-08-16 17:52:43 +020015966 /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
Takashi Iwaice577e82009-08-03 08:23:52 +020015967 SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
Takashi Iwai542d7c62007-08-16 18:57:30 +020015968 SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
Tobin Davisb419f342008-03-07 11:57:51 +010015969 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
Takashi Iwai39c5d412007-08-15 16:24:17 +020015970 SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +010015971 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
Tobin Davis625dc0b2007-07-30 21:42:10 +020015972 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015973 {}
15974};
15975
15976static struct alc_config_preset alc861vd_presets[] = {
15977 [ALC660VD_3ST] = {
15978 .mixers = { alc861vd_3st_mixer },
15979 .init_verbs = { alc861vd_volume_init_verbs,
15980 alc861vd_3stack_init_verbs },
15981 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
15982 .dac_nids = alc660vd_dac_nids,
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015983 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15984 .channel_mode = alc861vd_3stack_2ch_modes,
15985 .input_mux = &alc861vd_capture_source,
15986 },
Mike Crash6963f842007-06-25 12:12:51 +020015987 [ALC660VD_3ST_DIG] = {
15988 .mixers = { alc861vd_3st_mixer },
15989 .init_verbs = { alc861vd_volume_init_verbs,
15990 alc861vd_3stack_init_verbs },
15991 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
15992 .dac_nids = alc660vd_dac_nids,
15993 .dig_out_nid = ALC861VD_DIGOUT_NID,
Mike Crash6963f842007-06-25 12:12:51 +020015994 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15995 .channel_mode = alc861vd_3stack_2ch_modes,
15996 .input_mux = &alc861vd_capture_source,
15997 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015998 [ALC861VD_3ST] = {
15999 .mixers = { alc861vd_3st_mixer },
16000 .init_verbs = { alc861vd_volume_init_verbs,
16001 alc861vd_3stack_init_verbs },
16002 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16003 .dac_nids = alc861vd_dac_nids,
16004 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16005 .channel_mode = alc861vd_3stack_2ch_modes,
16006 .input_mux = &alc861vd_capture_source,
16007 },
16008 [ALC861VD_3ST_DIG] = {
16009 .mixers = { alc861vd_3st_mixer },
16010 .init_verbs = { alc861vd_volume_init_verbs,
16011 alc861vd_3stack_init_verbs },
16012 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16013 .dac_nids = alc861vd_dac_nids,
16014 .dig_out_nid = ALC861VD_DIGOUT_NID,
16015 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16016 .channel_mode = alc861vd_3stack_2ch_modes,
16017 .input_mux = &alc861vd_capture_source,
16018 },
16019 [ALC861VD_6ST_DIG] = {
16020 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
16021 .init_verbs = { alc861vd_volume_init_verbs,
16022 alc861vd_6stack_init_verbs },
16023 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16024 .dac_nids = alc861vd_dac_nids,
16025 .dig_out_nid = ALC861VD_DIGOUT_NID,
16026 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
16027 .channel_mode = alc861vd_6stack_modes,
16028 .input_mux = &alc861vd_capture_source,
16029 },
Kailang Yangbdd148a2007-05-08 15:19:08 +020016030 [ALC861VD_LENOVO] = {
16031 .mixers = { alc861vd_lenovo_mixer },
16032 .init_verbs = { alc861vd_volume_init_verbs,
16033 alc861vd_3stack_init_verbs,
16034 alc861vd_eapd_verbs,
16035 alc861vd_lenovo_unsol_verbs },
16036 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
16037 .dac_nids = alc660vd_dac_nids,
Kailang Yangbdd148a2007-05-08 15:19:08 +020016038 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16039 .channel_mode = alc861vd_3stack_2ch_modes,
16040 .input_mux = &alc861vd_capture_source,
16041 .unsol_event = alc861vd_lenovo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016042 .setup = alc861vd_lenovo_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016043 .init_hook = alc861vd_lenovo_init_hook,
Kailang Yangbdd148a2007-05-08 15:19:08 +020016044 },
Kailang Yang272a5272007-05-14 11:00:38 +020016045 [ALC861VD_DALLAS] = {
16046 .mixers = { alc861vd_dallas_mixer },
16047 .init_verbs = { alc861vd_dallas_verbs },
16048 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16049 .dac_nids = alc861vd_dac_nids,
Kailang Yang272a5272007-05-14 11:00:38 +020016050 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16051 .channel_mode = alc861vd_3stack_2ch_modes,
16052 .input_mux = &alc861vd_dallas_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016053 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016054 .setup = alc861vd_dallas_setup,
16055 .init_hook = alc_automute_amp,
Kailang Yangd1a991a2007-08-15 16:21:59 +020016056 },
16057 [ALC861VD_HP] = {
16058 .mixers = { alc861vd_hp_mixer },
16059 .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
16060 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16061 .dac_nids = alc861vd_dac_nids,
Kailang Yangd1a991a2007-08-15 16:21:59 +020016062 .dig_out_nid = ALC861VD_DIGOUT_NID,
Kailang Yangd1a991a2007-08-15 16:21:59 +020016063 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16064 .channel_mode = alc861vd_3stack_2ch_modes,
16065 .input_mux = &alc861vd_hp_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016066 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016067 .setup = alc861vd_dallas_setup,
16068 .init_hook = alc_automute_amp,
Kailang Yangea1fb292008-08-26 12:58:38 +020016069 },
Takashi Iwai13c94742008-11-05 08:06:08 +010016070 [ALC660VD_ASUS_V1S] = {
16071 .mixers = { alc861vd_lenovo_mixer },
16072 .init_verbs = { alc861vd_volume_init_verbs,
16073 alc861vd_3stack_init_verbs,
16074 alc861vd_eapd_verbs,
16075 alc861vd_lenovo_unsol_verbs },
16076 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
16077 .dac_nids = alc660vd_dac_nids,
16078 .dig_out_nid = ALC861VD_DIGOUT_NID,
16079 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16080 .channel_mode = alc861vd_3stack_2ch_modes,
16081 .input_mux = &alc861vd_capture_source,
16082 .unsol_event = alc861vd_lenovo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016083 .setup = alc861vd_lenovo_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016084 .init_hook = alc861vd_lenovo_init_hook,
Takashi Iwai13c94742008-11-05 08:06:08 +010016085 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016086};
16087
16088/*
16089 * BIOS auto configuration
16090 */
Takashi Iwai05f5f472009-08-25 13:10:18 +020016091static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
16092 const struct auto_pin_cfg *cfg)
16093{
Kailang Yang6227cdc2010-02-25 08:36:52 +010016094 return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
Takashi Iwai05f5f472009-08-25 13:10:18 +020016095}
16096
16097
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016098static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
16099 hda_nid_t nid, int pin_type, int dac_idx)
16100{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016101 alc_set_pin_output(codec, nid, pin_type);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016102}
16103
16104static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
16105{
16106 struct alc_spec *spec = codec->spec;
16107 int i;
16108
16109 for (i = 0; i <= HDA_SIDE; i++) {
16110 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020016111 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016112 if (nid)
16113 alc861vd_auto_set_output_and_unmute(codec, nid,
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020016114 pin_type, i);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016115 }
16116}
16117
16118
16119static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
16120{
16121 struct alc_spec *spec = codec->spec;
16122 hda_nid_t pin;
16123
16124 pin = spec->autocfg.hp_pins[0];
Sasha Alexandrdef319f2009-06-16 16:00:15 -040016125 if (pin) /* connect to front and use dac 0 */
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016126 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016127 pin = spec->autocfg.speaker_pins[0];
16128 if (pin)
16129 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016130}
16131
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016132#define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID
16133
16134static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
16135{
16136 struct alc_spec *spec = codec->spec;
16137 int i;
16138
16139 for (i = 0; i < AUTO_PIN_LAST; i++) {
16140 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai05f5f472009-08-25 13:10:18 +020016141 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +010016142 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +010016143 if (nid != ALC861VD_PIN_CD_NID &&
16144 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016145 snd_hda_codec_write(codec, nid, 0,
16146 AC_VERB_SET_AMP_GAIN_MUTE,
16147 AMP_OUT_MUTE);
16148 }
16149 }
16150}
16151
Takashi Iwaif511b012008-08-15 16:46:42 +020016152#define alc861vd_auto_init_input_src alc882_auto_init_input_src
16153
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016154#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)
16155#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)
16156
16157/* add playback controls from the parsed DAC table */
16158/* Based on ALC880 version. But ALC861VD has separate,
16159 * different NIDs for mute/unmute switch and volume control */
16160static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
16161 const struct auto_pin_cfg *cfg)
16162{
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016163 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
16164 hda_nid_t nid_v, nid_s;
16165 int i, err;
16166
16167 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016168 if (!spec->multiout.dac_nids[i])
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016169 continue;
16170 nid_v = alc861vd_idx_to_mixer_vol(
16171 alc880_dac_to_idx(
16172 spec->multiout.dac_nids[i]));
16173 nid_s = alc861vd_idx_to_mixer_switch(
16174 alc880_dac_to_idx(
16175 spec->multiout.dac_nids[i]));
16176
16177 if (i == 2) {
16178 /* Center/LFE */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016179 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
16180 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016181 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
16182 HDA_OUTPUT));
16183 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016184 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016185 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
16186 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016187 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
16188 HDA_OUTPUT));
16189 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016190 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016191 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
16192 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016193 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
16194 HDA_INPUT));
16195 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016196 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016197 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
16198 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016199 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
16200 HDA_INPUT));
16201 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016202 return err;
16203 } else {
Takashi Iwaia4fcd492009-08-25 16:12:15 +020016204 const char *pfx;
16205 if (cfg->line_outs == 1 &&
16206 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
16207 if (!cfg->hp_pins)
16208 pfx = "Speaker";
16209 else
16210 pfx = "PCM";
16211 } else
16212 pfx = chname[i];
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016213 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016214 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
16215 HDA_OUTPUT));
16216 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016217 return err;
Takashi Iwaia4fcd492009-08-25 16:12:15 +020016218 if (cfg->line_outs == 1 &&
16219 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
16220 pfx = "Speaker";
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016221 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Kailang Yangbdd148a2007-05-08 15:19:08 +020016222 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016223 HDA_INPUT));
16224 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016225 return err;
16226 }
16227 }
16228 return 0;
16229}
16230
16231/* add playback controls for speaker and HP outputs */
16232/* Based on ALC880 version. But ALC861VD has separate,
16233 * different NIDs for mute/unmute switch and volume control */
16234static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
16235 hda_nid_t pin, const char *pfx)
16236{
16237 hda_nid_t nid_v, nid_s;
16238 int err;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016239
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016240 if (!pin)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016241 return 0;
16242
16243 if (alc880_is_fixed_pin(pin)) {
16244 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
16245 /* specify the DAC as the extra output */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016246 if (!spec->multiout.hp_nid)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016247 spec->multiout.hp_nid = nid_v;
16248 else
16249 spec->multiout.extra_out_nid[0] = nid_v;
16250 /* control HP volume/switch on the output mixer amp */
16251 nid_v = alc861vd_idx_to_mixer_vol(
16252 alc880_fixed_pin_idx(pin));
16253 nid_s = alc861vd_idx_to_mixer_switch(
16254 alc880_fixed_pin_idx(pin));
16255
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016256 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016257 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
16258 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016259 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016260 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016261 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
16262 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016263 return err;
16264 } else if (alc880_is_multi_pin(pin)) {
16265 /* set manual connection */
16266 /* we have only a switch on HP-out PIN */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016267 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016268 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
16269 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016270 return err;
16271 }
16272 return 0;
16273}
16274
16275/* parse the BIOS configuration and set up the alc_spec
16276 * return 1 if successful, 0 if the proper config is not found,
16277 * or a negative error code
16278 * Based on ALC880 version - had to change it to override
16279 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
16280static int alc861vd_parse_auto_config(struct hda_codec *codec)
16281{
16282 struct alc_spec *spec = codec->spec;
16283 int err;
16284 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
16285
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016286 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
16287 alc861vd_ignore);
16288 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016289 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016290 if (!spec->autocfg.line_outs)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016291 return 0; /* can't find valid BIOS pin config */
16292
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016293 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
16294 if (err < 0)
16295 return err;
16296 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
16297 if (err < 0)
16298 return err;
16299 err = alc861vd_auto_create_extra_out(spec,
16300 spec->autocfg.speaker_pins[0],
16301 "Speaker");
16302 if (err < 0)
16303 return err;
16304 err = alc861vd_auto_create_extra_out(spec,
16305 spec->autocfg.hp_pins[0],
16306 "Headphone");
16307 if (err < 0)
16308 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020016309 err = alc861vd_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016310 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016311 return err;
16312
16313 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
16314
Takashi Iwai0852d7a2009-02-11 11:35:15 +010016315 if (spec->autocfg.dig_outs)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016316 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
16317
Takashi Iwai603c4012008-07-30 15:01:44 +020016318 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010016319 add_mixer(spec, spec->kctls.list);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016320
Takashi Iwaid88897e2008-10-31 15:01:37 +010016321 add_verb(spec, alc861vd_volume_init_verbs);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016322
16323 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020016324 spec->input_mux = &spec->private_imux[0];
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016325
Takashi Iwai776e1842007-08-29 15:07:11 +020016326 err = alc_auto_add_mic_boost(codec);
16327 if (err < 0)
16328 return err;
16329
Kailang Yang6227cdc2010-02-25 08:36:52 +010016330 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020016331
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016332 return 1;
16333}
16334
16335/* additional initialization for auto-configuration model */
16336static void alc861vd_auto_init(struct hda_codec *codec)
16337{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016338 struct alc_spec *spec = codec->spec;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016339 alc861vd_auto_init_multi_out(codec);
16340 alc861vd_auto_init_hp_out(codec);
16341 alc861vd_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020016342 alc861vd_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016343 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020016344 alc_inithook(codec);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016345}
16346
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016347enum {
16348 ALC660VD_FIX_ASUS_GPIO1
16349};
16350
16351/* reset GPIO1 */
16352static const struct hda_verb alc660vd_fix_asus_gpio1_verbs[] = {
16353 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
16354 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
16355 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
16356 { }
16357};
16358
16359static const struct alc_fixup alc861vd_fixups[] = {
16360 [ALC660VD_FIX_ASUS_GPIO1] = {
16361 .verbs = alc660vd_fix_asus_gpio1_verbs,
16362 },
16363};
16364
16365static struct snd_pci_quirk alc861vd_fixup_tbl[] = {
16366 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
16367 {}
16368};
16369
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016370static int patch_alc861vd(struct hda_codec *codec)
16371{
16372 struct alc_spec *spec;
16373 int err, board_config;
16374
16375 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
16376 if (spec == NULL)
16377 return -ENOMEM;
16378
16379 codec->spec = spec;
16380
16381 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
16382 alc861vd_models,
16383 alc861vd_cfg_tbl);
16384
16385 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020016386 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
16387 codec->chip_name);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016388 board_config = ALC861VD_AUTO;
16389 }
16390
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016391 alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups);
16392
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016393 if (board_config == ALC861VD_AUTO) {
16394 /* automatic parse from the BIOS config */
16395 err = alc861vd_parse_auto_config(codec);
16396 if (err < 0) {
16397 alc_free(codec);
16398 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016399 } else if (!err) {
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016400 printk(KERN_INFO
16401 "hda_codec: Cannot set up configuration "
16402 "from BIOS. Using base mode...\n");
16403 board_config = ALC861VD_3ST;
16404 }
16405 }
16406
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090016407 err = snd_hda_attach_beep_device(codec, 0x23);
16408 if (err < 0) {
16409 alc_free(codec);
16410 return err;
16411 }
16412
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016413 if (board_config != ALC861VD_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020016414 setup_preset(codec, &alc861vd_presets[board_config]);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016415
Kailang Yang2f893282008-05-27 12:14:47 +020016416 if (codec->vendor_id == 0x10ec0660) {
Kailang Yangf9423e72008-05-27 12:32:25 +020016417 /* always turn on EAPD */
Takashi Iwaid88897e2008-10-31 15:01:37 +010016418 add_verb(spec, alc660vd_eapd_verbs);
Kailang Yang2f893282008-05-27 12:14:47 +020016419 }
16420
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016421 spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
16422 spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
16423
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016424 spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
16425 spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
16426
Takashi Iwaidd704692009-08-11 08:45:11 +020016427 if (!spec->adc_nids) {
16428 spec->adc_nids = alc861vd_adc_nids;
16429 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
16430 }
16431 if (!spec->capsrc_nids)
16432 spec->capsrc_nids = alc861vd_capsrc_nids;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016433
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016434 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010016435 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016436
Takashi Iwai2134ea42008-01-10 16:53:55 +010016437 spec->vmaster_nid = 0x02;
16438
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016439 codec->patch_ops = alc_patch_ops;
16440
16441 if (board_config == ALC861VD_AUTO)
16442 spec->init_hook = alc861vd_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020016443#ifdef CONFIG_SND_HDA_POWER_SAVE
16444 if (!spec->loopback.amplist)
16445 spec->loopback.amplist = alc861vd_loopbacks;
16446#endif
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016447
16448 return 0;
16449}
16450
16451/*
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016452 * ALC662 support
16453 *
16454 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
16455 * configuration. Each pin widget can choose any input DACs and a mixer.
16456 * Each ADC is connected from a mixer of all inputs. This makes possible
16457 * 6-channel independent captures.
16458 *
16459 * In addition, an independent DAC for the multi-playback (not used in this
16460 * driver yet).
16461 */
16462#define ALC662_DIGOUT_NID 0x06
16463#define ALC662_DIGIN_NID 0x0a
16464
16465static hda_nid_t alc662_dac_nids[4] = {
16466 /* front, rear, clfe, rear_surr */
16467 0x02, 0x03, 0x04
16468};
16469
Kailang Yang622e84c2009-04-21 07:39:04 +020016470static hda_nid_t alc272_dac_nids[2] = {
16471 0x02, 0x03
16472};
16473
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016474static hda_nid_t alc662_adc_nids[2] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016475 /* ADC1-2 */
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016476 0x09, 0x08
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016477};
Takashi Iwaie1406342008-02-11 18:32:32 +010016478
Kailang Yang622e84c2009-04-21 07:39:04 +020016479static hda_nid_t alc272_adc_nids[1] = {
16480 /* ADC1-2 */
16481 0x08,
16482};
16483
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016484static hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
Kailang Yang622e84c2009-04-21 07:39:04 +020016485static hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
16486
Takashi Iwaie1406342008-02-11 18:32:32 +010016487
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016488/* input MUX */
16489/* FIXME: should be a matrix-type input source selection */
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016490static struct hda_input_mux alc662_capture_source = {
16491 .num_items = 4,
16492 .items = {
16493 { "Mic", 0x0 },
16494 { "Front Mic", 0x1 },
16495 { "Line", 0x2 },
16496 { "CD", 0x4 },
16497 },
16498};
16499
16500static struct hda_input_mux alc662_lenovo_101e_capture_source = {
16501 .num_items = 2,
16502 .items = {
16503 { "Mic", 0x1 },
16504 { "Line", 0x2 },
16505 },
16506};
Kailang Yang291702f2007-10-16 14:28:03 +020016507
Kailang Yang6dda9f42008-05-27 12:05:31 +020016508static struct hda_input_mux alc663_capture_source = {
16509 .num_items = 3,
16510 .items = {
16511 { "Mic", 0x0 },
16512 { "Front Mic", 0x1 },
16513 { "Line", 0x2 },
16514 },
16515};
16516
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016517#if 0 /* set to 1 for testing other input sources below */
Chris Pockelé9541ba12009-05-12 08:08:53 +020016518static struct hda_input_mux alc272_nc10_capture_source = {
16519 .num_items = 16,
16520 .items = {
16521 { "Autoselect Mic", 0x0 },
16522 { "Internal Mic", 0x1 },
16523 { "In-0x02", 0x2 },
16524 { "In-0x03", 0x3 },
16525 { "In-0x04", 0x4 },
16526 { "In-0x05", 0x5 },
16527 { "In-0x06", 0x6 },
16528 { "In-0x07", 0x7 },
16529 { "In-0x08", 0x8 },
16530 { "In-0x09", 0x9 },
16531 { "In-0x0a", 0x0a },
16532 { "In-0x0b", 0x0b },
16533 { "In-0x0c", 0x0c },
16534 { "In-0x0d", 0x0d },
16535 { "In-0x0e", 0x0e },
16536 { "In-0x0f", 0x0f },
16537 },
16538};
16539#endif
16540
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016541/*
16542 * 2ch mode
16543 */
16544static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
16545 { 2, NULL }
16546};
16547
16548/*
16549 * 2ch mode
16550 */
16551static struct hda_verb alc662_3ST_ch2_init[] = {
16552 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
16553 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
16554 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
16555 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
16556 { } /* end */
16557};
16558
16559/*
16560 * 6ch mode
16561 */
16562static struct hda_verb alc662_3ST_ch6_init[] = {
16563 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16564 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
16565 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
16566 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16567 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
16568 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
16569 { } /* end */
16570};
16571
16572static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
16573 { 2, alc662_3ST_ch2_init },
16574 { 6, alc662_3ST_ch6_init },
16575};
16576
16577/*
16578 * 2ch mode
16579 */
16580static struct hda_verb alc662_sixstack_ch6_init[] = {
16581 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
16582 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
16583 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16584 { } /* end */
16585};
16586
16587/*
16588 * 6ch mode
16589 */
16590static struct hda_verb alc662_sixstack_ch8_init[] = {
16591 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16592 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16593 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16594 { } /* end */
16595};
16596
16597static struct hda_channel_mode alc662_5stack_modes[2] = {
16598 { 2, alc662_sixstack_ch6_init },
16599 { 6, alc662_sixstack_ch8_init },
16600};
16601
16602/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
16603 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
16604 */
16605
16606static struct snd_kcontrol_new alc662_base_mixer[] = {
16607 /* output mixer control */
16608 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016609 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016610 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016611 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016612 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
16613 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016614 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
16615 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016616 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16617
16618 /*Input mixer control */
16619 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
16620 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
16621 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
16622 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
16623 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
16624 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
16625 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
16626 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016627 { } /* end */
16628};
16629
16630static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
16631 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016632 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016633 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16634 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16635 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16636 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16637 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16638 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16639 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16640 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16641 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016642 { } /* end */
16643};
16644
16645static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
16646 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016647 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016648 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016649 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016650 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
16651 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016652 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
16653 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016654 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16655 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16656 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16657 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16658 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16659 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16660 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16661 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16662 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016663 { } /* end */
16664};
16665
16666static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
16667 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16668 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +010016669 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16670 HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016671 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16672 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16673 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16674 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16675 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016676 { } /* end */
16677};
16678
Kailang Yang291702f2007-10-16 14:28:03 +020016679static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020016680 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16681 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang291702f2007-10-16 14:28:03 +020016682
16683 HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT),
16684 HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16685 HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16686
16687 HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),
16688 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16689 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16690 { } /* end */
16691};
16692
Kailang Yang8c427222008-01-10 13:03:59 +010016693static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020016694 ALC262_HIPPO_MASTER_SWITCH,
16695 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010016696 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010016697 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
16698 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010016699 HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
16700 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16701 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16702 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16703 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16704 { } /* end */
16705};
16706
Kailang Yangf1d4e282008-08-26 14:03:29 +020016707static struct hda_bind_ctls alc663_asus_bind_master_vol = {
16708 .ops = &snd_hda_bind_vol,
16709 .values = {
16710 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
16711 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
16712 0
16713 },
16714};
16715
16716static struct hda_bind_ctls alc663_asus_one_bind_switch = {
16717 .ops = &snd_hda_bind_sw,
16718 .values = {
16719 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16720 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
16721 0
16722 },
16723};
16724
Kailang Yang6dda9f42008-05-27 12:05:31 +020016725static struct snd_kcontrol_new alc663_m51va_mixer[] = {
Kailang Yangf1d4e282008-08-26 14:03:29 +020016726 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
16727 HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
16728 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16729 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16730 { } /* end */
16731};
16732
16733static struct hda_bind_ctls alc663_asus_tree_bind_switch = {
16734 .ops = &snd_hda_bind_sw,
16735 .values = {
16736 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16737 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
16738 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
16739 0
16740 },
16741};
16742
16743static struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
16744 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
16745 HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
16746 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16747 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16748 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16749 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16750
16751 { } /* end */
16752};
16753
16754static struct hda_bind_ctls alc663_asus_four_bind_switch = {
16755 .ops = &snd_hda_bind_sw,
16756 .values = {
16757 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16758 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
16759 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
16760 0
16761 },
16762};
16763
16764static struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
16765 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
16766 HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
16767 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16768 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16769 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16770 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16771 { } /* end */
16772};
16773
16774static struct snd_kcontrol_new alc662_1bjd_mixer[] = {
Kailang Yang6dda9f42008-05-27 12:05:31 +020016775 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16776 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Kailang Yangf1d4e282008-08-26 14:03:29 +020016777 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16778 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16779 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16780 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16781 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16782 { } /* end */
16783};
16784
16785static struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
16786 .ops = &snd_hda_bind_vol,
16787 .values = {
16788 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
16789 HDA_COMPOSE_AMP_VAL(0x04, 3, 0, HDA_OUTPUT),
16790 0
16791 },
16792};
16793
16794static struct hda_bind_ctls alc663_asus_two_bind_switch = {
16795 .ops = &snd_hda_bind_sw,
16796 .values = {
16797 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16798 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT),
16799 0
16800 },
16801};
16802
16803static struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
16804 HDA_BIND_VOL("Master Playback Volume",
16805 &alc663_asus_two_bind_master_vol),
16806 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
16807 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yang6dda9f42008-05-27 12:05:31 +020016808 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16809 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16810 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangf1d4e282008-08-26 14:03:29 +020016811 { } /* end */
16812};
16813
16814static struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
16815 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
16816 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
16817 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16818 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
16819 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16820 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yang6dda9f42008-05-27 12:05:31 +020016821 { } /* end */
16822};
16823
16824static struct snd_kcontrol_new alc663_g71v_mixer[] = {
16825 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16826 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
16827 HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16828 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
16829 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16830
16831 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16832 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16833 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16834 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16835 { } /* end */
16836};
16837
16838static struct snd_kcontrol_new alc663_g50v_mixer[] = {
16839 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16840 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
16841 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16842
16843 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16844 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16845 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16846 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16847 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16848 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16849 { } /* end */
16850};
16851
Kailang Yangebb83ee2009-12-17 12:23:00 +010016852static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
16853 .ops = &snd_hda_bind_sw,
16854 .values = {
16855 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16856 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
16857 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
16858 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
16859 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
16860 0
16861 },
16862};
16863
16864static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
16865 .ops = &snd_hda_bind_sw,
16866 .values = {
16867 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16868 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
16869 0
16870 },
16871};
16872
16873static struct snd_kcontrol_new alc663_mode7_mixer[] = {
16874 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
16875 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
16876 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
16877 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16878 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16879 HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16880 HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16881 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16882 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16883 { } /* end */
16884};
16885
16886static struct snd_kcontrol_new alc663_mode8_mixer[] = {
16887 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
16888 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
16889 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
16890 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
16891 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16892 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16893 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16894 { } /* end */
16895};
16896
16897
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016898static struct snd_kcontrol_new alc662_chmode_mixer[] = {
16899 {
16900 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16901 .name = "Channel Mode",
16902 .info = alc_ch_mode_info,
16903 .get = alc_ch_mode_get,
16904 .put = alc_ch_mode_put,
16905 },
16906 { } /* end */
16907};
16908
16909static struct hda_verb alc662_init_verbs[] = {
16910 /* ADC: mute amp left and right */
16911 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16912 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016913
Kailang Yangb60dd392007-09-20 12:50:29 +020016914 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16915 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16916 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16917 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16918 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16919 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016920
16921 /* Front Pin: output 0 (0x0c) */
16922 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16923 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16924
16925 /* Rear Pin: output 1 (0x0d) */
16926 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16927 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16928
16929 /* CLFE Pin: output 2 (0x0e) */
16930 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16931 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16932
16933 /* Mic (rear) pin: input vref at 80% */
16934 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16935 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16936 /* Front Mic pin: input vref at 80% */
16937 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16938 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16939 /* Line In pin: input */
16940 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16941 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16942 /* Line-2 In: Headphone output (output 0 - 0x0c) */
16943 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16944 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16945 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
16946 /* CD pin widget for input */
16947 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16948
16949 /* FIXME: use matrix-type input source selection */
16950 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
16951 /* Input mixer */
16952 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yang291702f2007-10-16 14:28:03 +020016953 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yang6dda9f42008-05-27 12:05:31 +020016954
16955 /* always trun on EAPD */
16956 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
16957 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
16958
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016959 { }
16960};
16961
Kailang Yangcec27c82010-02-04 14:18:18 +010016962static struct hda_verb alc663_init_verbs[] = {
16963 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16964 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16965 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16966 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16967 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16968 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16969 { }
16970};
16971
16972static struct hda_verb alc272_init_verbs[] = {
16973 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16974 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16975 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16976 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16977 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16978 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16979 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16980 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16981 { }
16982};
16983
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016984static struct hda_verb alc662_sue_init_verbs[] = {
16985 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
16986 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
Kailang Yang291702f2007-10-16 14:28:03 +020016987 {}
16988};
16989
16990static struct hda_verb alc662_eeepc_sue_init_verbs[] = {
16991 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16992 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16993 {}
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016994};
16995
Kailang Yang8c427222008-01-10 13:03:59 +010016996/* Set Unsolicited Event*/
16997static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
16998 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16999 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17000 {}
17001};
17002
Kailang Yang6dda9f42008-05-27 12:05:31 +020017003static struct hda_verb alc663_m51va_init_verbs[] = {
Kailang Yangf1d4e282008-08-26 14:03:29 +020017004 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17005 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yang6dda9f42008-05-27 12:05:31 +020017006 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17007 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangf1d4e282008-08-26 14:03:29 +020017008 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17009 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17010 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
Kailang Yang6dda9f42008-05-27 12:05:31 +020017011 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17012 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17013 {}
17014};
17015
Kailang Yangf1d4e282008-08-26 14:03:29 +020017016static struct hda_verb alc663_21jd_amic_init_verbs[] = {
17017 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17018 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17019 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17020 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17021 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17022 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17023 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17024 {}
17025};
17026
17027static struct hda_verb alc662_1bjd_amic_init_verbs[] = {
17028 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17029 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17030 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17031 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
17032 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17033 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17034 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17035 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17036 {}
17037};
17038
17039static struct hda_verb alc663_15jd_amic_init_verbs[] = {
17040 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17041 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17042 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17043 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17044 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17045 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17046 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17047 {}
17048};
17049
17050static struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
17051 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17052 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17053 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17054 {0x21, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
17055 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17056 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17057 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
17058 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17059 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17060 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17061 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17062 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17063 {}
17064};
17065
17066static struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
17067 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17068 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17069 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17070 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17071 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17072 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17073 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17074 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17075 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17076 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17077 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17078 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17079 {}
17080};
17081
Kailang Yang6dda9f42008-05-27 12:05:31 +020017082static struct hda_verb alc663_g71v_init_verbs[] = {
17083 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17084 /* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
17085 /* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
17086
17087 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17088 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17089 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
17090
17091 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
17092 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
17093 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
17094 {}
17095};
17096
17097static struct hda_verb alc663_g50v_init_verbs[] = {
17098 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17099 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17100 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
17101
17102 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17103 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17104 {}
17105};
17106
Kailang Yangf1d4e282008-08-26 14:03:29 +020017107static struct hda_verb alc662_ecs_init_verbs[] = {
17108 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
17109 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17110 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17111 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17112 {}
17113};
17114
Kailang Yang622e84c2009-04-21 07:39:04 +020017115static struct hda_verb alc272_dell_zm1_init_verbs[] = {
17116 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17117 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17118 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17119 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17120 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17121 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17122 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17123 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17124 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
17125 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17126 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17127 {}
17128};
17129
17130static struct hda_verb alc272_dell_init_verbs[] = {
17131 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17132 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17133 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17134 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17135 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17136 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17137 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17138 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17139 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
17140 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17141 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17142 {}
17143};
17144
Kailang Yangebb83ee2009-12-17 12:23:00 +010017145static struct hda_verb alc663_mode7_init_verbs[] = {
17146 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17147 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17148 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17149 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17150 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17151 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17152 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
17153 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17154 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17155 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17156 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17157 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
17158 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17159 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17160 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17161 {}
17162};
17163
17164static struct hda_verb alc663_mode8_init_verbs[] = {
17165 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17166 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17167 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17168 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
17169 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17170 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17171 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17172 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17173 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17174 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17175 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17176 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17177 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
17178 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17179 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17180 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17181 {}
17182};
17183
Kailang Yangf1d4e282008-08-26 14:03:29 +020017184static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
17185 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
17186 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
17187 { } /* end */
17188};
17189
Kailang Yang622e84c2009-04-21 07:39:04 +020017190static struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
17191 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
17192 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
17193 { } /* end */
17194};
17195
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017196static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
17197{
17198 unsigned int present;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017199 unsigned char bits;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017200
Wu Fengguang864f92b2009-11-18 12:38:02 +080017201 present = snd_hda_jack_detect(codec, 0x14);
Takashi Iwai47fd8302007-08-10 17:11:07 +020017202 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080017203
Takashi Iwai47fd8302007-08-10 17:11:07 +020017204 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
17205 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017206}
17207
17208static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
17209{
17210 unsigned int present;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017211 unsigned char bits;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017212
Wu Fengguang864f92b2009-11-18 12:38:02 +080017213 present = snd_hda_jack_detect(codec, 0x1b);
Takashi Iwai47fd8302007-08-10 17:11:07 +020017214 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080017215
Takashi Iwai47fd8302007-08-10 17:11:07 +020017216 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
17217 HDA_AMP_MUTE, bits);
17218 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
17219 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017220}
17221
17222static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
17223 unsigned int res)
17224{
17225 if ((res >> 26) == ALC880_HP_EVENT)
17226 alc662_lenovo_101e_all_automute(codec);
17227 if ((res >> 26) == ALC880_FRONT_EVENT)
17228 alc662_lenovo_101e_ispeaker_automute(codec);
17229}
17230
Kailang Yang291702f2007-10-16 14:28:03 +020017231/* unsolicited event for HP jack sensing */
17232static void alc662_eeepc_unsol_event(struct hda_codec *codec,
17233 unsigned int res)
17234{
Kailang Yang291702f2007-10-16 14:28:03 +020017235 if ((res >> 26) == ALC880_MIC_EVENT)
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017236 alc_mic_automute(codec);
Takashi Iwai42171c12009-05-08 14:11:43 +020017237 else
17238 alc262_hippo_unsol_event(codec, res);
Kailang Yang291702f2007-10-16 14:28:03 +020017239}
17240
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017241static void alc662_eeepc_setup(struct hda_codec *codec)
Kailang Yang291702f2007-10-16 14:28:03 +020017242{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017243 struct alc_spec *spec = codec->spec;
17244
17245 alc262_hippo1_setup(codec);
17246 spec->ext_mic.pin = 0x18;
17247 spec->ext_mic.mux_idx = 0;
17248 spec->int_mic.pin = 0x19;
17249 spec->int_mic.mux_idx = 1;
17250 spec->auto_mic = 1;
Kailang Yang291702f2007-10-16 14:28:03 +020017251}
17252
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017253static void alc662_eeepc_inithook(struct hda_codec *codec)
17254{
17255 alc262_hippo_automute(codec);
17256 alc_mic_automute(codec);
17257}
17258
17259static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
Kailang Yang8c427222008-01-10 13:03:59 +010017260{
Takashi Iwai42171c12009-05-08 14:11:43 +020017261 struct alc_spec *spec = codec->spec;
17262
17263 spec->autocfg.hp_pins[0] = 0x14;
17264 spec->autocfg.speaker_pins[0] = 0x1b;
Kailang Yang8c427222008-01-10 13:03:59 +010017265}
17266
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017267#define alc662_eeepc_ep20_inithook alc262_hippo_master_update
17268
Kailang Yang6dda9f42008-05-27 12:05:31 +020017269static void alc663_m51va_speaker_automute(struct hda_codec *codec)
17270{
17271 unsigned int present;
17272 unsigned char bits;
17273
Wu Fengguang864f92b2009-11-18 12:38:02 +080017274 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017275 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yangf1d4e282008-08-26 14:03:29 +020017276 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017277 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017278 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017279 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017280}
17281
17282static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
17283{
17284 unsigned int present;
17285 unsigned char bits;
17286
Wu Fengguang864f92b2009-11-18 12:38:02 +080017287 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017288 bits = present ? HDA_AMP_MUTE : 0;
17289 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017290 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017291 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017292 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017293 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017294 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017295 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017296 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017297}
17298
17299static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
17300{
17301 unsigned int present;
17302 unsigned char bits;
17303
Wu Fengguang864f92b2009-11-18 12:38:02 +080017304 present = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017305 bits = present ? HDA_AMP_MUTE : 0;
17306 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017307 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017308 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017309 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017310 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017311 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017312 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017313 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017314}
17315
17316static void alc662_f5z_speaker_automute(struct hda_codec *codec)
17317{
17318 unsigned int present;
17319 unsigned char bits;
17320
Wu Fengguang864f92b2009-11-18 12:38:02 +080017321 present = snd_hda_jack_detect(codec, 0x1b);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017322 bits = present ? 0 : PIN_OUT;
17323 snd_hda_codec_write(codec, 0x14, 0,
17324 AC_VERB_SET_PIN_WIDGET_CONTROL, bits);
17325}
17326
17327static void alc663_two_hp_m1_speaker_automute(struct hda_codec *codec)
17328{
17329 unsigned int present1, present2;
17330
Wu Fengguang864f92b2009-11-18 12:38:02 +080017331 present1 = snd_hda_jack_detect(codec, 0x21);
17332 present2 = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017333
17334 if (present1 || present2) {
17335 snd_hda_codec_write_cache(codec, 0x14, 0,
17336 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17337 } else {
17338 snd_hda_codec_write_cache(codec, 0x14, 0,
17339 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17340 }
17341}
17342
17343static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
17344{
17345 unsigned int present1, present2;
17346
Wu Fengguang864f92b2009-11-18 12:38:02 +080017347 present1 = snd_hda_jack_detect(codec, 0x1b);
17348 present2 = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017349
17350 if (present1 || present2) {
17351 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017352 HDA_AMP_MUTE, HDA_AMP_MUTE);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017353 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017354 HDA_AMP_MUTE, HDA_AMP_MUTE);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017355 } else {
17356 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017357 HDA_AMP_MUTE, 0);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017358 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017359 HDA_AMP_MUTE, 0);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017360 }
Kailang Yang6dda9f42008-05-27 12:05:31 +020017361}
17362
Kailang Yangebb83ee2009-12-17 12:23:00 +010017363static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec)
17364{
17365 unsigned int present1, present2;
17366
17367 present1 = snd_hda_codec_read(codec, 0x1b, 0,
17368 AC_VERB_GET_PIN_SENSE, 0)
17369 & AC_PINSENSE_PRESENCE;
17370 present2 = snd_hda_codec_read(codec, 0x21, 0,
17371 AC_VERB_GET_PIN_SENSE, 0)
17372 & AC_PINSENSE_PRESENCE;
17373
17374 if (present1 || present2) {
17375 snd_hda_codec_write_cache(codec, 0x14, 0,
17376 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17377 snd_hda_codec_write_cache(codec, 0x17, 0,
17378 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17379 } else {
17380 snd_hda_codec_write_cache(codec, 0x14, 0,
17381 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17382 snd_hda_codec_write_cache(codec, 0x17, 0,
17383 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17384 }
17385}
17386
17387static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec)
17388{
17389 unsigned int present1, present2;
17390
17391 present1 = snd_hda_codec_read(codec, 0x21, 0,
17392 AC_VERB_GET_PIN_SENSE, 0)
17393 & AC_PINSENSE_PRESENCE;
17394 present2 = snd_hda_codec_read(codec, 0x15, 0,
17395 AC_VERB_GET_PIN_SENSE, 0)
17396 & AC_PINSENSE_PRESENCE;
17397
17398 if (present1 || present2) {
17399 snd_hda_codec_write_cache(codec, 0x14, 0,
17400 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17401 snd_hda_codec_write_cache(codec, 0x17, 0,
17402 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17403 } else {
17404 snd_hda_codec_write_cache(codec, 0x14, 0,
17405 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17406 snd_hda_codec_write_cache(codec, 0x17, 0,
17407 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17408 }
17409}
17410
Kailang Yang6dda9f42008-05-27 12:05:31 +020017411static void alc663_m51va_unsol_event(struct hda_codec *codec,
17412 unsigned int res)
17413{
17414 switch (res >> 26) {
17415 case ALC880_HP_EVENT:
17416 alc663_m51va_speaker_automute(codec);
17417 break;
17418 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017419 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017420 break;
17421 }
17422}
17423
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017424static void alc663_m51va_setup(struct hda_codec *codec)
17425{
17426 struct alc_spec *spec = codec->spec;
17427 spec->ext_mic.pin = 0x18;
17428 spec->ext_mic.mux_idx = 0;
17429 spec->int_mic.pin = 0x12;
Kailang Yangebb83ee2009-12-17 12:23:00 +010017430 spec->int_mic.mux_idx = 9;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017431 spec->auto_mic = 1;
17432}
17433
Kailang Yang6dda9f42008-05-27 12:05:31 +020017434static void alc663_m51va_inithook(struct hda_codec *codec)
17435{
17436 alc663_m51va_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017437 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017438}
17439
Kailang Yangf1d4e282008-08-26 14:03:29 +020017440/* ***************** Mode1 ******************************/
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017441#define alc663_mode1_unsol_event alc663_m51va_unsol_event
Kailang Yangebb83ee2009-12-17 12:23:00 +010017442
17443static void alc663_mode1_setup(struct hda_codec *codec)
17444{
17445 struct alc_spec *spec = codec->spec;
17446 spec->ext_mic.pin = 0x18;
17447 spec->ext_mic.mux_idx = 0;
17448 spec->int_mic.pin = 0x19;
17449 spec->int_mic.mux_idx = 1;
17450 spec->auto_mic = 1;
17451}
17452
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017453#define alc663_mode1_inithook alc663_m51va_inithook
Kailang Yangf1d4e282008-08-26 14:03:29 +020017454
Kailang Yangf1d4e282008-08-26 14:03:29 +020017455/* ***************** Mode2 ******************************/
17456static void alc662_mode2_unsol_event(struct hda_codec *codec,
17457 unsigned int res)
17458{
17459 switch (res >> 26) {
17460 case ALC880_HP_EVENT:
17461 alc662_f5z_speaker_automute(codec);
17462 break;
17463 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017464 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017465 break;
17466 }
17467}
17468
Kailang Yangebb83ee2009-12-17 12:23:00 +010017469#define alc662_mode2_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017470
Kailang Yangf1d4e282008-08-26 14:03:29 +020017471static void alc662_mode2_inithook(struct hda_codec *codec)
17472{
17473 alc662_f5z_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017474 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017475}
17476/* ***************** Mode3 ******************************/
17477static void alc663_mode3_unsol_event(struct hda_codec *codec,
17478 unsigned int res)
17479{
17480 switch (res >> 26) {
17481 case ALC880_HP_EVENT:
17482 alc663_two_hp_m1_speaker_automute(codec);
17483 break;
17484 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017485 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017486 break;
17487 }
17488}
17489
Kailang Yangebb83ee2009-12-17 12:23:00 +010017490#define alc663_mode3_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017491
Kailang Yangf1d4e282008-08-26 14:03:29 +020017492static void alc663_mode3_inithook(struct hda_codec *codec)
17493{
17494 alc663_two_hp_m1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017495 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017496}
17497/* ***************** Mode4 ******************************/
17498static void alc663_mode4_unsol_event(struct hda_codec *codec,
17499 unsigned int res)
17500{
17501 switch (res >> 26) {
17502 case ALC880_HP_EVENT:
17503 alc663_21jd_two_speaker_automute(codec);
17504 break;
17505 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017506 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017507 break;
17508 }
17509}
17510
Kailang Yangebb83ee2009-12-17 12:23:00 +010017511#define alc663_mode4_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017512
Kailang Yangf1d4e282008-08-26 14:03:29 +020017513static void alc663_mode4_inithook(struct hda_codec *codec)
17514{
17515 alc663_21jd_two_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017516 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017517}
17518/* ***************** Mode5 ******************************/
17519static void alc663_mode5_unsol_event(struct hda_codec *codec,
17520 unsigned int res)
17521{
17522 switch (res >> 26) {
17523 case ALC880_HP_EVENT:
17524 alc663_15jd_two_speaker_automute(codec);
17525 break;
17526 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017527 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017528 break;
17529 }
17530}
17531
Kailang Yangebb83ee2009-12-17 12:23:00 +010017532#define alc663_mode5_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017533
Kailang Yangf1d4e282008-08-26 14:03:29 +020017534static void alc663_mode5_inithook(struct hda_codec *codec)
17535{
17536 alc663_15jd_two_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017537 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017538}
17539/* ***************** Mode6 ******************************/
17540static void alc663_mode6_unsol_event(struct hda_codec *codec,
17541 unsigned int res)
17542{
17543 switch (res >> 26) {
17544 case ALC880_HP_EVENT:
17545 alc663_two_hp_m2_speaker_automute(codec);
17546 break;
17547 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017548 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017549 break;
17550 }
17551}
17552
Kailang Yangebb83ee2009-12-17 12:23:00 +010017553#define alc663_mode6_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017554
Kailang Yangf1d4e282008-08-26 14:03:29 +020017555static void alc663_mode6_inithook(struct hda_codec *codec)
17556{
17557 alc663_two_hp_m2_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017558 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017559}
17560
Kailang Yangebb83ee2009-12-17 12:23:00 +010017561/* ***************** Mode7 ******************************/
17562static void alc663_mode7_unsol_event(struct hda_codec *codec,
17563 unsigned int res)
17564{
17565 switch (res >> 26) {
17566 case ALC880_HP_EVENT:
17567 alc663_two_hp_m7_speaker_automute(codec);
17568 break;
17569 case ALC880_MIC_EVENT:
17570 alc_mic_automute(codec);
17571 break;
17572 }
17573}
17574
17575#define alc663_mode7_setup alc663_mode1_setup
17576
17577static void alc663_mode7_inithook(struct hda_codec *codec)
17578{
17579 alc663_two_hp_m7_speaker_automute(codec);
17580 alc_mic_automute(codec);
17581}
17582
17583/* ***************** Mode8 ******************************/
17584static void alc663_mode8_unsol_event(struct hda_codec *codec,
17585 unsigned int res)
17586{
17587 switch (res >> 26) {
17588 case ALC880_HP_EVENT:
17589 alc663_two_hp_m8_speaker_automute(codec);
17590 break;
17591 case ALC880_MIC_EVENT:
17592 alc_mic_automute(codec);
17593 break;
17594 }
17595}
17596
17597#define alc663_mode8_setup alc663_m51va_setup
17598
17599static void alc663_mode8_inithook(struct hda_codec *codec)
17600{
17601 alc663_two_hp_m8_speaker_automute(codec);
17602 alc_mic_automute(codec);
17603}
17604
Kailang Yang6dda9f42008-05-27 12:05:31 +020017605static void alc663_g71v_hp_automute(struct hda_codec *codec)
17606{
17607 unsigned int present;
17608 unsigned char bits;
17609
Wu Fengguang864f92b2009-11-18 12:38:02 +080017610 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017611 bits = present ? HDA_AMP_MUTE : 0;
17612 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
17613 HDA_AMP_MUTE, bits);
17614 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
17615 HDA_AMP_MUTE, bits);
17616}
17617
17618static void alc663_g71v_front_automute(struct hda_codec *codec)
17619{
17620 unsigned int present;
17621 unsigned char bits;
17622
Wu Fengguang864f92b2009-11-18 12:38:02 +080017623 present = snd_hda_jack_detect(codec, 0x15);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017624 bits = present ? HDA_AMP_MUTE : 0;
17625 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
17626 HDA_AMP_MUTE, bits);
17627}
17628
17629static void alc663_g71v_unsol_event(struct hda_codec *codec,
17630 unsigned int res)
17631{
17632 switch (res >> 26) {
17633 case ALC880_HP_EVENT:
17634 alc663_g71v_hp_automute(codec);
17635 break;
17636 case ALC880_FRONT_EVENT:
17637 alc663_g71v_front_automute(codec);
17638 break;
17639 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017640 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017641 break;
17642 }
17643}
17644
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017645#define alc663_g71v_setup alc663_m51va_setup
17646
Kailang Yang6dda9f42008-05-27 12:05:31 +020017647static void alc663_g71v_inithook(struct hda_codec *codec)
17648{
17649 alc663_g71v_front_automute(codec);
17650 alc663_g71v_hp_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017651 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017652}
17653
17654static void alc663_g50v_unsol_event(struct hda_codec *codec,
17655 unsigned int res)
17656{
17657 switch (res >> 26) {
17658 case ALC880_HP_EVENT:
17659 alc663_m51va_speaker_automute(codec);
17660 break;
17661 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017662 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017663 break;
17664 }
17665}
17666
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017667#define alc663_g50v_setup alc663_m51va_setup
17668
Kailang Yang6dda9f42008-05-27 12:05:31 +020017669static void alc663_g50v_inithook(struct hda_codec *codec)
17670{
17671 alc663_m51va_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017672 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017673}
17674
Kailang Yangf1d4e282008-08-26 14:03:29 +020017675static struct snd_kcontrol_new alc662_ecs_mixer[] = {
17676 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Takashi Iwai42171c12009-05-08 14:11:43 +020017677 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017678
17679 HDA_CODEC_VOLUME("e-Mic/LineIn Boost", 0x18, 0, HDA_INPUT),
17680 HDA_CODEC_VOLUME("e-Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
17681 HDA_CODEC_MUTE("e-Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT),
17682
17683 HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),
17684 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17685 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17686 { } /* end */
17687};
17688
Chris Pockelé9541ba12009-05-12 08:08:53 +020017689static struct snd_kcontrol_new alc272_nc10_mixer[] = {
17690 /* Master Playback automatically created from Speaker and Headphone */
17691 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17692 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17693 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17694 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17695
17696 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17697 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17698 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
17699
17700 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17701 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17702 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
17703 { } /* end */
17704};
17705
Takashi Iwaicb53c622007-08-10 17:21:45 +020017706#ifdef CONFIG_SND_HDA_POWER_SAVE
17707#define alc662_loopbacks alc880_loopbacks
17708#endif
17709
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017710
Sasha Alexandrdef319f2009-06-16 16:00:15 -040017711/* pcm configuration: identical with ALC880 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017712#define alc662_pcm_analog_playback alc880_pcm_analog_playback
17713#define alc662_pcm_analog_capture alc880_pcm_analog_capture
17714#define alc662_pcm_digital_playback alc880_pcm_digital_playback
17715#define alc662_pcm_digital_capture alc880_pcm_digital_capture
17716
17717/*
17718 * configuration and preset
17719 */
17720static const char *alc662_models[ALC662_MODEL_LAST] = {
17721 [ALC662_3ST_2ch_DIG] = "3stack-dig",
17722 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
17723 [ALC662_3ST_6ch] = "3stack-6ch",
17724 [ALC662_5ST_DIG] = "6stack-dig",
17725 [ALC662_LENOVO_101E] = "lenovo-101e",
Takashi Iwaib995d762007-10-17 10:41:06 +020017726 [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
Kailang Yang8c427222008-01-10 13:03:59 +010017727 [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
Kailang Yangf1d4e282008-08-26 14:03:29 +020017728 [ALC662_ECS] = "ecs",
Kailang Yang6dda9f42008-05-27 12:05:31 +020017729 [ALC663_ASUS_M51VA] = "m51va",
17730 [ALC663_ASUS_G71V] = "g71v",
17731 [ALC663_ASUS_H13] = "h13",
17732 [ALC663_ASUS_G50V] = "g50v",
Kailang Yangf1d4e282008-08-26 14:03:29 +020017733 [ALC663_ASUS_MODE1] = "asus-mode1",
17734 [ALC662_ASUS_MODE2] = "asus-mode2",
17735 [ALC663_ASUS_MODE3] = "asus-mode3",
17736 [ALC663_ASUS_MODE4] = "asus-mode4",
17737 [ALC663_ASUS_MODE5] = "asus-mode5",
17738 [ALC663_ASUS_MODE6] = "asus-mode6",
Kailang Yangebb83ee2009-12-17 12:23:00 +010017739 [ALC663_ASUS_MODE7] = "asus-mode7",
17740 [ALC663_ASUS_MODE8] = "asus-mode8",
Takashi Iwai01f2bd42009-05-11 08:12:43 +020017741 [ALC272_DELL] = "dell",
17742 [ALC272_DELL_ZM1] = "dell-zm1",
Chris Pockelé9541ba12009-05-12 08:08:53 +020017743 [ALC272_SAMSUNG_NC10] = "samsung-nc10",
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017744 [ALC662_AUTO] = "auto",
17745};
17746
17747static struct snd_pci_quirk alc662_cfg_tbl[] = {
Takashi Iwaidea0a502009-02-09 17:14:52 +010017748 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
Kailang Yang622e84c2009-04-21 07:39:04 +020017749 SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
17750 SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017751 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
17752 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
Kailang Yangcec27c82010-02-04 14:18:18 +010017753 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017754 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
17755 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
17756 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
17757 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
Kailang Yangebb83ee2009-12-17 12:23:00 +010017758 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
17759 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017760 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010017761 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
17762 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
17763 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
17764 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
17765 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017766 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010017767 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
17768 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017769 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
17770 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
17771 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
17772 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010017773 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
Kailang Yang622e84c2009-04-21 07:39:04 +020017774 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
17775 SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
17776 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017777 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
17778 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
17779 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
17780 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020017781 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017782 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
17783 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yang6dda9f42008-05-27 12:05:31 +020017784 SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017785 /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
17786 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
17787 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
Kailang Yang622e84c2009-04-21 07:39:04 +020017788 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
Kailang Yangcec27c82010-02-04 14:18:18 +010017789 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
Kailang Yang622e84c2009-04-21 07:39:04 +020017790 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
17791 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017792 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
17793 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
17794 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020017795 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017796 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
17797 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
Kailang Yang622e84c2009-04-21 07:39:04 +020017798 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017799 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
Kailang Yang80ffe862008-10-15 11:23:27 +020017800 SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017801 /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
17802 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
17803 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020017804 SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017805 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
17806 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
Herton Ronaldo Krzesinski3da23ca2008-03-14 12:52:59 +010017807 SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
Kailang Yang291702f2007-10-16 14:28:03 +020017808 SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
Kailang Yang8c427222008-01-10 13:03:59 +010017809 SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017810 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
Herton Ronaldo Krzesinski95fe5f22008-09-26 23:48:45 -030017811 SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
17812 ALC662_3ST_6ch_DIG),
Takashi Iwai4dee8ba2010-01-13 17:20:08 +010017813 SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
Chris Pockelé9541ba12009-05-12 08:08:53 +020017814 SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
Herton Ronaldo Krzesinskicb559742008-09-26 23:47:45 -030017815 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
17816 ALC662_3ST_6ch_DIG),
Kailang Yang6227cdc2010-02-25 08:36:52 +010017817 SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
Vedran Miletic19c009a2008-09-29 20:29:25 +020017818 SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
Takashi Iwai5bd37292009-04-21 18:36:30 +020017819 SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017820 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
Takashi Iwai238713d2008-10-05 10:57:39 +020017821 SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
Vedran Miletic19c009a2008-09-29 20:29:25 +020017822 ALC662_3ST_6ch_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017823 SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
17824 ALC663_ASUS_H13),
David Santinoli7aee6742009-12-09 12:34:26 +010017825 SND_PCI_QUIRK(0x8086, 0xd604, "Intel mobo", ALC662_3ST_2ch_DIG),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017826 {}
17827};
17828
17829static struct alc_config_preset alc662_presets[] = {
17830 [ALC662_3ST_2ch_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017831 .mixers = { alc662_3ST_2ch_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017832 .init_verbs = { alc662_init_verbs },
17833 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17834 .dac_nids = alc662_dac_nids,
17835 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017836 .dig_in_nid = ALC662_DIGIN_NID,
17837 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17838 .channel_mode = alc662_3ST_2ch_modes,
17839 .input_mux = &alc662_capture_source,
17840 },
17841 [ALC662_3ST_6ch_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017842 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017843 .init_verbs = { alc662_init_verbs },
17844 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17845 .dac_nids = alc662_dac_nids,
17846 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017847 .dig_in_nid = ALC662_DIGIN_NID,
17848 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
17849 .channel_mode = alc662_3ST_6ch_modes,
17850 .need_dac_fix = 1,
17851 .input_mux = &alc662_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017852 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017853 [ALC662_3ST_6ch] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017854 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017855 .init_verbs = { alc662_init_verbs },
17856 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17857 .dac_nids = alc662_dac_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017858 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
17859 .channel_mode = alc662_3ST_6ch_modes,
17860 .need_dac_fix = 1,
17861 .input_mux = &alc662_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017862 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017863 [ALC662_5ST_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017864 .mixers = { alc662_base_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017865 .init_verbs = { alc662_init_verbs },
17866 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17867 .dac_nids = alc662_dac_nids,
17868 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017869 .dig_in_nid = ALC662_DIGIN_NID,
17870 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
17871 .channel_mode = alc662_5stack_modes,
17872 .input_mux = &alc662_capture_source,
17873 },
17874 [ALC662_LENOVO_101E] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017875 .mixers = { alc662_lenovo_101e_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017876 .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
17877 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17878 .dac_nids = alc662_dac_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017879 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17880 .channel_mode = alc662_3ST_2ch_modes,
17881 .input_mux = &alc662_lenovo_101e_capture_source,
17882 .unsol_event = alc662_lenovo_101e_unsol_event,
17883 .init_hook = alc662_lenovo_101e_all_automute,
17884 },
Kailang Yang291702f2007-10-16 14:28:03 +020017885 [ALC662_ASUS_EEEPC_P701] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017886 .mixers = { alc662_eeepc_p701_mixer },
Kailang Yang291702f2007-10-16 14:28:03 +020017887 .init_verbs = { alc662_init_verbs,
17888 alc662_eeepc_sue_init_verbs },
17889 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17890 .dac_nids = alc662_dac_nids,
Kailang Yang291702f2007-10-16 14:28:03 +020017891 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17892 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang291702f2007-10-16 14:28:03 +020017893 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017894 .setup = alc662_eeepc_setup,
Kailang Yang291702f2007-10-16 14:28:03 +020017895 .init_hook = alc662_eeepc_inithook,
17896 },
Kailang Yang8c427222008-01-10 13:03:59 +010017897 [ALC662_ASUS_EEEPC_EP20] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017898 .mixers = { alc662_eeepc_ep20_mixer,
Kailang Yang8c427222008-01-10 13:03:59 +010017899 alc662_chmode_mixer },
17900 .init_verbs = { alc662_init_verbs,
17901 alc662_eeepc_ep20_sue_init_verbs },
17902 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17903 .dac_nids = alc662_dac_nids,
Kailang Yang8c427222008-01-10 13:03:59 +010017904 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
17905 .channel_mode = alc662_3ST_6ch_modes,
17906 .input_mux = &alc662_lenovo_101e_capture_source,
Takashi Iwai42171c12009-05-08 14:11:43 +020017907 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017908 .setup = alc662_eeepc_ep20_setup,
Kailang Yang8c427222008-01-10 13:03:59 +010017909 .init_hook = alc662_eeepc_ep20_inithook,
17910 },
Kailang Yangf1d4e282008-08-26 14:03:29 +020017911 [ALC662_ECS] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017912 .mixers = { alc662_ecs_mixer },
Kailang Yangf1d4e282008-08-26 14:03:29 +020017913 .init_verbs = { alc662_init_verbs,
17914 alc662_ecs_init_verbs },
17915 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17916 .dac_nids = alc662_dac_nids,
17917 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17918 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017919 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017920 .setup = alc662_eeepc_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017921 .init_hook = alc662_eeepc_inithook,
17922 },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017923 [ALC663_ASUS_M51VA] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017924 .mixers = { alc663_m51va_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017925 .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
17926 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17927 .dac_nids = alc662_dac_nids,
17928 .dig_out_nid = ALC662_DIGOUT_NID,
17929 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17930 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017931 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017932 .setup = alc663_m51va_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017933 .init_hook = alc663_m51va_inithook,
17934 },
17935 [ALC663_ASUS_G71V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017936 .mixers = { alc663_g71v_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017937 .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
17938 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17939 .dac_nids = alc662_dac_nids,
17940 .dig_out_nid = ALC662_DIGOUT_NID,
17941 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17942 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017943 .unsol_event = alc663_g71v_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017944 .setup = alc663_g71v_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017945 .init_hook = alc663_g71v_inithook,
17946 },
17947 [ALC663_ASUS_H13] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017948 .mixers = { alc663_m51va_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017949 .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
17950 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17951 .dac_nids = alc662_dac_nids,
17952 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17953 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017954 .unsol_event = alc663_m51va_unsol_event,
17955 .init_hook = alc663_m51va_inithook,
17956 },
17957 [ALC663_ASUS_G50V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017958 .mixers = { alc663_g50v_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017959 .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
17960 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17961 .dac_nids = alc662_dac_nids,
17962 .dig_out_nid = ALC662_DIGOUT_NID,
17963 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
17964 .channel_mode = alc662_3ST_6ch_modes,
17965 .input_mux = &alc663_capture_source,
17966 .unsol_event = alc663_g50v_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017967 .setup = alc663_g50v_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017968 .init_hook = alc663_g50v_inithook,
17969 },
Kailang Yangf1d4e282008-08-26 14:03:29 +020017970 [ALC663_ASUS_MODE1] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017971 .mixers = { alc663_m51va_mixer },
17972 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017973 .init_verbs = { alc662_init_verbs,
17974 alc663_21jd_amic_init_verbs },
17975 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17976 .hp_nid = 0x03,
17977 .dac_nids = alc662_dac_nids,
17978 .dig_out_nid = ALC662_DIGOUT_NID,
17979 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17980 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017981 .unsol_event = alc663_mode1_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017982 .setup = alc663_mode1_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017983 .init_hook = alc663_mode1_inithook,
17984 },
17985 [ALC662_ASUS_MODE2] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017986 .mixers = { alc662_1bjd_mixer },
17987 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017988 .init_verbs = { alc662_init_verbs,
17989 alc662_1bjd_amic_init_verbs },
17990 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17991 .dac_nids = alc662_dac_nids,
17992 .dig_out_nid = ALC662_DIGOUT_NID,
17993 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17994 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017995 .unsol_event = alc662_mode2_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017996 .setup = alc662_mode2_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017997 .init_hook = alc662_mode2_inithook,
17998 },
17999 [ALC663_ASUS_MODE3] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018000 .mixers = { alc663_two_hp_m1_mixer },
18001 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018002 .init_verbs = { alc662_init_verbs,
18003 alc663_two_hp_amic_m1_init_verbs },
18004 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18005 .hp_nid = 0x03,
18006 .dac_nids = alc662_dac_nids,
18007 .dig_out_nid = ALC662_DIGOUT_NID,
18008 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18009 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018010 .unsol_event = alc663_mode3_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018011 .setup = alc663_mode3_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018012 .init_hook = alc663_mode3_inithook,
18013 },
18014 [ALC663_ASUS_MODE4] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018015 .mixers = { alc663_asus_21jd_clfe_mixer },
18016 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018017 .init_verbs = { alc662_init_verbs,
18018 alc663_21jd_amic_init_verbs},
18019 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18020 .hp_nid = 0x03,
18021 .dac_nids = alc662_dac_nids,
18022 .dig_out_nid = ALC662_DIGOUT_NID,
18023 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18024 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018025 .unsol_event = alc663_mode4_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018026 .setup = alc663_mode4_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018027 .init_hook = alc663_mode4_inithook,
18028 },
18029 [ALC663_ASUS_MODE5] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018030 .mixers = { alc663_asus_15jd_clfe_mixer },
18031 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018032 .init_verbs = { alc662_init_verbs,
18033 alc663_15jd_amic_init_verbs },
18034 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18035 .hp_nid = 0x03,
18036 .dac_nids = alc662_dac_nids,
18037 .dig_out_nid = ALC662_DIGOUT_NID,
18038 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18039 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018040 .unsol_event = alc663_mode5_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018041 .setup = alc663_mode5_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018042 .init_hook = alc663_mode5_inithook,
18043 },
18044 [ALC663_ASUS_MODE6] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018045 .mixers = { alc663_two_hp_m2_mixer },
18046 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018047 .init_verbs = { alc662_init_verbs,
18048 alc663_two_hp_amic_m2_init_verbs },
18049 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18050 .hp_nid = 0x03,
18051 .dac_nids = alc662_dac_nids,
18052 .dig_out_nid = ALC662_DIGOUT_NID,
18053 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18054 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018055 .unsol_event = alc663_mode6_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018056 .setup = alc663_mode6_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018057 .init_hook = alc663_mode6_inithook,
18058 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010018059 [ALC663_ASUS_MODE7] = {
18060 .mixers = { alc663_mode7_mixer },
18061 .cap_mixer = alc662_auto_capture_mixer,
18062 .init_verbs = { alc662_init_verbs,
18063 alc663_mode7_init_verbs },
18064 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18065 .hp_nid = 0x03,
18066 .dac_nids = alc662_dac_nids,
18067 .dig_out_nid = ALC662_DIGOUT_NID,
18068 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18069 .channel_mode = alc662_3ST_2ch_modes,
18070 .unsol_event = alc663_mode7_unsol_event,
18071 .setup = alc663_mode7_setup,
18072 .init_hook = alc663_mode7_inithook,
18073 },
18074 [ALC663_ASUS_MODE8] = {
18075 .mixers = { alc663_mode8_mixer },
18076 .cap_mixer = alc662_auto_capture_mixer,
18077 .init_verbs = { alc662_init_verbs,
18078 alc663_mode8_init_verbs },
18079 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18080 .hp_nid = 0x03,
18081 .dac_nids = alc662_dac_nids,
18082 .dig_out_nid = ALC662_DIGOUT_NID,
18083 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18084 .channel_mode = alc662_3ST_2ch_modes,
18085 .unsol_event = alc663_mode8_unsol_event,
18086 .setup = alc663_mode8_setup,
18087 .init_hook = alc663_mode8_inithook,
18088 },
Kailang Yang622e84c2009-04-21 07:39:04 +020018089 [ALC272_DELL] = {
18090 .mixers = { alc663_m51va_mixer },
18091 .cap_mixer = alc272_auto_capture_mixer,
18092 .init_verbs = { alc662_init_verbs, alc272_dell_init_verbs },
18093 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18094 .dac_nids = alc662_dac_nids,
18095 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18096 .adc_nids = alc272_adc_nids,
18097 .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
18098 .capsrc_nids = alc272_capsrc_nids,
18099 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang622e84c2009-04-21 07:39:04 +020018100 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018101 .setup = alc663_m51va_setup,
Kailang Yang622e84c2009-04-21 07:39:04 +020018102 .init_hook = alc663_m51va_inithook,
18103 },
18104 [ALC272_DELL_ZM1] = {
18105 .mixers = { alc663_m51va_mixer },
18106 .cap_mixer = alc662_auto_capture_mixer,
18107 .init_verbs = { alc662_init_verbs, alc272_dell_zm1_init_verbs },
18108 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18109 .dac_nids = alc662_dac_nids,
18110 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18111 .adc_nids = alc662_adc_nids,
Takashi Iwaib59bdf32009-08-11 09:47:30 +020018112 .num_adc_nids = 1,
Kailang Yang622e84c2009-04-21 07:39:04 +020018113 .capsrc_nids = alc662_capsrc_nids,
18114 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang622e84c2009-04-21 07:39:04 +020018115 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018116 .setup = alc663_m51va_setup,
Kailang Yang622e84c2009-04-21 07:39:04 +020018117 .init_hook = alc663_m51va_inithook,
18118 },
Chris Pockelé9541ba12009-05-12 08:08:53 +020018119 [ALC272_SAMSUNG_NC10] = {
18120 .mixers = { alc272_nc10_mixer },
18121 .init_verbs = { alc662_init_verbs,
18122 alc663_21jd_amic_init_verbs },
18123 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18124 .dac_nids = alc272_dac_nids,
18125 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18126 .channel_mode = alc662_3ST_2ch_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018127 /*.input_mux = &alc272_nc10_capture_source,*/
Chris Pockelé9541ba12009-05-12 08:08:53 +020018128 .unsol_event = alc663_mode4_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018129 .setup = alc663_mode4_setup,
Chris Pockelé9541ba12009-05-12 08:08:53 +020018130 .init_hook = alc663_mode4_inithook,
18131 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018132};
18133
18134
18135/*
18136 * BIOS auto configuration
18137 */
18138
Takashi Iwai7085ec12009-10-02 09:03:58 +020018139/* convert from MIX nid to DAC */
18140static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
18141{
18142 if (nid == 0x0f)
18143 return 0x02;
18144 else if (nid >= 0x0c && nid <= 0x0e)
18145 return nid - 0x0c + 0x02;
18146 else
18147 return 0;
18148}
18149
18150/* get MIX nid connected to the given pin targeted to DAC */
18151static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
18152 hda_nid_t dac)
18153{
18154 hda_nid_t mix[4];
18155 int i, num;
18156
18157 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
18158 for (i = 0; i < num; i++) {
18159 if (alc662_mix_to_dac(mix[i]) == dac)
18160 return mix[i];
18161 }
18162 return 0;
18163}
18164
18165/* look for an empty DAC slot */
18166static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
18167{
18168 struct alc_spec *spec = codec->spec;
18169 hda_nid_t srcs[5];
18170 int i, j, num;
18171
18172 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
18173 if (num < 0)
18174 return 0;
18175 for (i = 0; i < num; i++) {
18176 hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
18177 if (!nid)
18178 continue;
18179 for (j = 0; j < spec->multiout.num_dacs; j++)
18180 if (spec->multiout.dac_nids[j] == nid)
18181 break;
18182 if (j >= spec->multiout.num_dacs)
18183 return nid;
18184 }
18185 return 0;
18186}
18187
18188/* fill in the dac_nids table from the parsed pin configuration */
18189static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
18190 const struct auto_pin_cfg *cfg)
18191{
18192 struct alc_spec *spec = codec->spec;
18193 int i;
18194 hda_nid_t dac;
18195
18196 spec->multiout.dac_nids = spec->private_dac_nids;
18197 for (i = 0; i < cfg->line_outs; i++) {
18198 dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
18199 if (!dac)
18200 continue;
18201 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
18202 }
18203 return 0;
18204}
18205
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018206static inline int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018207 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018208{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018209 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018210 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
18211}
18212
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018213static inline int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018214 hda_nid_t nid, unsigned int chs)
18215{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018216 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018217 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
18218}
18219
18220#define alc662_add_stereo_vol(spec, pfx, nid) \
18221 alc662_add_vol_ctl(spec, pfx, nid, 3)
18222#define alc662_add_stereo_sw(spec, pfx, nid) \
18223 alc662_add_sw_ctl(spec, pfx, nid, 3)
18224
18225/* add playback controls from the parsed DAC table */
18226static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
18227 const struct auto_pin_cfg *cfg)
18228{
18229 struct alc_spec *spec = codec->spec;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018230 static const char *chname[4] = {
18231 "Front", "Surround", NULL /*CLFE*/, "Side"
18232 };
Takashi Iwai7085ec12009-10-02 09:03:58 +020018233 hda_nid_t nid, mix;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018234 int i, err;
18235
18236 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018237 nid = spec->multiout.dac_nids[i];
18238 if (!nid)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018239 continue;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018240 mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
18241 if (!mix)
18242 continue;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018243 if (i == 2) {
18244 /* Center/LFE */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018245 err = alc662_add_vol_ctl(spec, "Center", nid, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018246 if (err < 0)
18247 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018248 err = alc662_add_vol_ctl(spec, "LFE", nid, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018249 if (err < 0)
18250 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018251 err = alc662_add_sw_ctl(spec, "Center", mix, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018252 if (err < 0)
18253 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018254 err = alc662_add_sw_ctl(spec, "LFE", mix, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018255 if (err < 0)
18256 return err;
18257 } else {
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018258 const char *pfx;
18259 if (cfg->line_outs == 1 &&
18260 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018261 if (cfg->hp_outs)
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018262 pfx = "Speaker";
18263 else
18264 pfx = "PCM";
18265 } else
18266 pfx = chname[i];
Takashi Iwai7085ec12009-10-02 09:03:58 +020018267 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018268 if (err < 0)
18269 return err;
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018270 if (cfg->line_outs == 1 &&
18271 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
18272 pfx = "Speaker";
Takashi Iwai7085ec12009-10-02 09:03:58 +020018273 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018274 if (err < 0)
18275 return err;
18276 }
18277 }
18278 return 0;
18279}
18280
18281/* add playback controls for speaker and HP outputs */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018282/* return DAC nid if any new DAC is assigned */
18283static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018284 const char *pfx)
18285{
Takashi Iwai7085ec12009-10-02 09:03:58 +020018286 struct alc_spec *spec = codec->spec;
18287 hda_nid_t nid, mix;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018288 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018289
18290 if (!pin)
18291 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018292 nid = alc662_look_for_dac(codec, pin);
18293 if (!nid) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018294 /* the corresponding DAC is already occupied */
18295 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
18296 return 0; /* no way */
18297 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018298 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018299 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
18300 }
18301
18302 mix = alc662_dac_to_mix(codec, pin, nid);
18303 if (!mix)
18304 return 0;
18305 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
18306 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +020018307 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018308 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
18309 if (err < 0)
18310 return err;
18311 return nid;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018312}
18313
18314/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020018315#define alc662_auto_create_input_ctls \
Takashi Iwai4b7348a2009-10-14 18:25:23 +020018316 alc882_auto_create_input_ctls
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018317
18318static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
18319 hda_nid_t nid, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018320 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018321{
Takashi Iwai7085ec12009-10-02 09:03:58 +020018322 int i, num;
18323 hda_nid_t srcs[4];
18324
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018325 alc_set_pin_output(codec, nid, pin_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018326 /* need the manual connection? */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018327 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
18328 if (num <= 1)
18329 return;
18330 for (i = 0; i < num; i++) {
18331 if (alc662_mix_to_dac(srcs[i]) != dac)
18332 continue;
18333 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
18334 return;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018335 }
18336}
18337
18338static void alc662_auto_init_multi_out(struct hda_codec *codec)
18339{
18340 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018341 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018342 int i;
18343
18344 for (i = 0; i <= HDA_SIDE; i++) {
18345 hda_nid_t nid = spec->autocfg.line_out_pins[i];
18346 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020018347 alc662_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018348 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018349 }
18350}
18351
18352static void alc662_auto_init_hp_out(struct hda_codec *codec)
18353{
18354 struct alc_spec *spec = codec->spec;
18355 hda_nid_t pin;
18356
18357 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +020018358 if (pin)
18359 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
18360 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018361 pin = spec->autocfg.speaker_pins[0];
18362 if (pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +020018363 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
18364 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018365}
18366
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018367#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
18368
18369static void alc662_auto_init_analog_input(struct hda_codec *codec)
18370{
18371 struct alc_spec *spec = codec->spec;
18372 int i;
18373
18374 for (i = 0; i < AUTO_PIN_LAST; i++) {
18375 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai05f5f472009-08-25 13:10:18 +020018376 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +010018377 alc_set_input_pin(codec, nid, i);
Takashi Iwai52ca15b2009-03-23 12:51:55 +010018378 if (nid != ALC662_PIN_CD_NID &&
Takashi Iwaie82c0252009-03-23 15:17:38 +010018379 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018380 snd_hda_codec_write(codec, nid, 0,
18381 AC_VERB_SET_AMP_GAIN_MUTE,
18382 AMP_OUT_MUTE);
18383 }
18384 }
18385}
18386
Takashi Iwaif511b012008-08-15 16:46:42 +020018387#define alc662_auto_init_input_src alc882_auto_init_input_src
18388
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018389static int alc662_parse_auto_config(struct hda_codec *codec)
18390{
18391 struct alc_spec *spec = codec->spec;
18392 int err;
18393 static hda_nid_t alc662_ignore[] = { 0x1d, 0 };
18394
18395 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
18396 alc662_ignore);
18397 if (err < 0)
18398 return err;
18399 if (!spec->autocfg.line_outs)
18400 return 0; /* can't find valid BIOS pin config */
18401
Takashi Iwai7085ec12009-10-02 09:03:58 +020018402 err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018403 if (err < 0)
18404 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018405 err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018406 if (err < 0)
18407 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018408 err = alc662_auto_create_extra_out(codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018409 spec->autocfg.speaker_pins[0],
18410 "Speaker");
18411 if (err < 0)
18412 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018413 if (err)
18414 spec->multiout.extra_out_nid[0] = err;
18415 err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018416 "Headphone");
18417 if (err < 0)
18418 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018419 if (err)
18420 spec->multiout.hp_nid = err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020018421 err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018422 if (err < 0)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018423 return err;
18424
18425 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
18426
Takashi Iwai0852d7a2009-02-11 11:35:15 +010018427 if (spec->autocfg.dig_outs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018428 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
18429
Takashi Iwai603c4012008-07-30 15:01:44 +020018430 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010018431 add_mixer(spec, spec->kctls.list);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018432
18433 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020018434 spec->input_mux = &spec->private_imux[0];
Kailang Yangea1fb292008-08-26 12:58:38 +020018435
Kailang Yangcec27c82010-02-04 14:18:18 +010018436 add_verb(spec, alc662_init_verbs);
18437 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
18438 codec->vendor_id == 0x10ec0665)
18439 add_verb(spec, alc663_init_verbs);
18440
18441 if (codec->vendor_id == 0x10ec0272)
18442 add_verb(spec, alc272_init_verbs);
Takashi Iwaiee979a142008-09-02 15:42:20 +020018443
18444 err = alc_auto_add_mic_boost(codec);
18445 if (err < 0)
18446 return err;
18447
Kailang Yang6227cdc2010-02-25 08:36:52 +010018448 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
18449 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
18450 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
18451 else
18452 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020018453
Takashi Iwai8c87286f2007-06-19 12:11:16 +020018454 return 1;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018455}
18456
18457/* additional initialization for auto-configuration model */
18458static void alc662_auto_init(struct hda_codec *codec)
18459{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018460 struct alc_spec *spec = codec->spec;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018461 alc662_auto_init_multi_out(codec);
18462 alc662_auto_init_hp_out(codec);
18463 alc662_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020018464 alc662_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018465 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020018466 alc_inithook(codec);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018467}
18468
18469static int patch_alc662(struct hda_codec *codec)
18470{
18471 struct alc_spec *spec;
18472 int err, board_config;
18473
18474 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
18475 if (!spec)
18476 return -ENOMEM;
18477
18478 codec->spec = spec;
18479
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +020018480 alc_fix_pll_init(codec, 0x20, 0x04, 15);
18481
Kailang Yang274693f2009-12-03 10:07:50 +010018482 if (alc_read_coef_idx(codec, 0)==0x8020){
18483 kfree(codec->chip_name);
18484 codec->chip_name = kstrdup("ALC661", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018485 if (!codec->chip_name) {
18486 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010018487 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018488 }
Kailang Yang274693f2009-12-03 10:07:50 +010018489 }
18490
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018491 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
18492 alc662_models,
18493 alc662_cfg_tbl);
18494 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020018495 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
18496 codec->chip_name);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018497 board_config = ALC662_AUTO;
18498 }
18499
18500 if (board_config == ALC662_AUTO) {
18501 /* automatic parse from the BIOS config */
18502 err = alc662_parse_auto_config(codec);
18503 if (err < 0) {
18504 alc_free(codec);
18505 return err;
Takashi Iwai8c87286f2007-06-19 12:11:16 +020018506 } else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018507 printk(KERN_INFO
18508 "hda_codec: Cannot set up configuration "
18509 "from BIOS. Using base mode...\n");
18510 board_config = ALC662_3ST_2ch_DIG;
18511 }
18512 }
18513
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090018514 err = snd_hda_attach_beep_device(codec, 0x1);
18515 if (err < 0) {
18516 alc_free(codec);
18517 return err;
18518 }
18519
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018520 if (board_config != ALC662_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020018521 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018522
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018523 spec->stream_analog_playback = &alc662_pcm_analog_playback;
18524 spec->stream_analog_capture = &alc662_pcm_analog_capture;
18525
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018526 spec->stream_digital_playback = &alc662_pcm_digital_playback;
18527 spec->stream_digital_capture = &alc662_pcm_digital_capture;
18528
Takashi Iwaidd704692009-08-11 08:45:11 +020018529 if (!spec->adc_nids) {
18530 spec->adc_nids = alc662_adc_nids;
18531 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
18532 }
18533 if (!spec->capsrc_nids)
18534 spec->capsrc_nids = alc662_capsrc_nids;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018535
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018536 if (!spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020018537 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018538
Kailang Yangcec27c82010-02-04 14:18:18 +010018539 switch (codec->vendor_id) {
18540 case 0x10ec0662:
18541 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
18542 break;
18543 case 0x10ec0272:
18544 case 0x10ec0663:
18545 case 0x10ec0665:
18546 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
18547 break;
18548 case 0x10ec0273:
18549 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
18550 break;
18551 }
Takashi Iwai2134ea42008-01-10 16:53:55 +010018552 spec->vmaster_nid = 0x02;
18553
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018554 codec->patch_ops = alc_patch_ops;
18555 if (board_config == ALC662_AUTO)
18556 spec->init_hook = alc662_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020018557#ifdef CONFIG_SND_HDA_POWER_SAVE
18558 if (!spec->loopback.amplist)
18559 spec->loopback.amplist = alc662_loopbacks;
18560#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018561
18562 return 0;
18563}
18564
Kailang Yang274693f2009-12-03 10:07:50 +010018565static int patch_alc888(struct hda_codec *codec)
18566{
18567 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
18568 kfree(codec->chip_name);
18569 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018570 if (!codec->chip_name) {
18571 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010018572 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018573 }
18574 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010018575 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018576 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010018577}
18578
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018579/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070018580 * patch entries
18581 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +010018582static struct hda_codec_preset snd_hda_preset_realtek[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070018583 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +010018584 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +010018585 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +020018586 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +010018587 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010018588 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +020018589 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010018590 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010018591 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018592 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010018593 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
18594 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
18595 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018596 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai4953550a2009-06-30 15:28:30 +020018597 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018598 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
18599 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +020018600 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +010018601 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +010018602 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010018603 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070018604 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai4953550a2009-06-30 15:28:30 +020018605 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +020018606 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +020018607 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +020018608 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +020018609 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +010018610 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Takashi Iwai4953550a2009-06-30 15:28:30 +020018611 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
Kailang Yang44426082008-10-15 11:18:05 +020018612 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai4953550a2009-06-30 15:28:30 +020018613 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +010018614 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai4953550a2009-06-30 15:28:30 +020018615 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +010018616 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070018617 {} /* terminator */
18618};
Takashi Iwai1289e9e2008-11-27 15:47:11 +010018619
18620MODULE_ALIAS("snd-hda-codec-id:10ec*");
18621
18622MODULE_LICENSE("GPL");
18623MODULE_DESCRIPTION("Realtek HD-audio codec");
18624
18625static struct hda_codec_preset_list realtek_list = {
18626 .preset = snd_hda_preset_realtek,
18627 .owner = THIS_MODULE,
18628};
18629
18630static int __init patch_realtek_init(void)
18631{
18632 return snd_hda_add_codec_preset(&realtek_list);
18633}
18634
18635static void __exit patch_realtek_exit(void)
18636{
18637 snd_hda_delete_codec_preset(&realtek_list);
18638}
18639
18640module_init(patch_realtek_init)
18641module_exit(patch_realtek_exit)