blob: 220a49ff21793ba190483ce122e547ca993dfe34 [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 Woithe7cf51e42006-02-09 12:01:26 +01009 * Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <sound/core.h>
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 Woithe7cf51e42006-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 Avdoninbab282b2006-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,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +0100233 ALC883_LAPTOP_EAPD,
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200234 ALC883_LENOVO_101E_2ch,
Kailang Yang272a5272007-05-14 11:00:38 +0200235 ALC883_LENOVO_NB0763,
Kailang Yang189609a2007-08-20 11:31:23 +0200236 ALC888_LENOVO_MS7195_DIG,
Kailang Yange2757d52008-08-26 13:17:46 +0200237 ALC888_LENOVO_SKY,
Kailang Yangea1fb292008-08-26 12:58:38 +0200238 ALC883_HAIER_W66,
Claudio Matsuoka4723c022007-07-13 14:36:19 +0200239 ALC888_3ST_HP,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +0100240 ALC888_6ST_DELL,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +0100241 ALC883_MITAC,
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -0430242 ALC883_CLEVO_M540R,
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +0100243 ALC883_CLEVO_M720,
Jiang zhefb97dc62008-03-06 11:07:11 +0100244 ALC883_FUJITSU_PI2515,
Vincent Petryef8ef5f2008-11-23 11:31:41 +0800245 ALC888_FUJITSU_XA3530,
Jiang zhe17bba1b2008-06-04 12:11:07 +0200246 ALC883_3ST_6ch_INTEL,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200247 ALC889A_INTEL,
248 ALC889_INTEL,
Kailang Yange2757d52008-08-26 13:17:46 +0200249 ALC888_ASUS_M90V,
250 ALC888_ASUS_EEE1601,
Torben Schulzeb4c41d2009-05-18 15:02:35 +0200251 ALC889A_MB31,
Wu Fengguang3ab90932008-11-17 09:51:09 +0100252 ALC1200_ASUS_P5Q,
Guido Günther3e1647c2009-06-05 00:47:26 +0200253 ALC883_SONY_VAIO_TT,
Takashi Iwai49535502009-06-30 15:28:30 +0200254 ALC882_AUTO,
255 ALC882_MODEL_LAST,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200256};
257
Kailang Yangdf694da2005-12-05 19:42:22 +0100258/* for GPIO Poll */
259#define GPIO_MASK 0x03
260
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200261/* extra amp-initialization sequence types */
262enum {
263 ALC_INIT_NONE,
264 ALC_INIT_DEFAULT,
265 ALC_INIT_GPIO1,
266 ALC_INIT_GPIO2,
267 ALC_INIT_GPIO3,
268};
269
Takashi Iwai6c819492009-08-10 18:47:44 +0200270struct alc_mic_route {
271 hda_nid_t pin;
272 unsigned char mux_idx;
273 unsigned char amix_idx;
274};
275
276#define MUX_IDX_UNDEF ((unsigned char)-1)
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278struct alc_spec {
279 /* codec parameterization */
Kailang Yangdf694da2005-12-05 19:42:22 +0100280 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 unsigned int num_mixers;
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100282 struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100283 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Takashi Iwai2d9c6482009-10-13 08:06:55 +0200285 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200286 * don't forget NULL
287 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200288 */
289 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200291 char stream_name_analog[32]; /* analog PCM stream */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 struct hda_pcm_stream *stream_analog_playback;
293 struct hda_pcm_stream *stream_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +0100294 struct hda_pcm_stream *stream_analog_alt_playback;
295 struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200297 char stream_name_digital[32]; /* digital PCM stream */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 struct hda_pcm_stream *stream_digital_playback;
299 struct hda_pcm_stream *stream_digital_capture;
300
301 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200302 struct hda_multi_out multiout; /* playback set-up
303 * max_channels, dacs must be set
304 * dig_out_nid and hp_nid are optional
305 */
Takashi Iwai63300792008-01-24 15:31:36 +0100306 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100307 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100308 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
310 /* capture */
311 unsigned int num_adc_nids;
312 hda_nid_t *adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100313 hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200314 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
316 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200317 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 const struct hda_input_mux *input_mux;
319 unsigned int cur_mux[3];
Takashi Iwai6c819492009-08-10 18:47:44 +0200320 struct alc_mic_route ext_mic;
321 struct alc_mic_route int_mic;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100324 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200326 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200327 int const_channel_count;
328 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100331 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200332
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200333 /* dynamic controls, init_verbs and input_mux */
334 struct auto_pin_cfg autocfg;
Takashi Iwai603c4012008-07-30 15:01:44 +0200335 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200336 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200337 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai49535502009-06-30 15:28:30 +0200338 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
339 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai834be882006-03-01 14:16:17 +0100340
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100341 /* hooks */
342 void (*init_hook)(struct hda_codec *codec);
343 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100344#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500345 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100346#endif
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100347
Takashi Iwai834be882006-03-01 14:16:17 +0100348 /* for pin sensing */
349 unsigned int sense_updated: 1;
350 unsigned int jack_present: 1;
Takashi Iwaibec15c32008-01-28 18:16:30 +0100351 unsigned int master_sw: 1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200352 unsigned int auto_mic:1;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200353
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100354 /* other flags */
355 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200356 int init_amp;
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100357
Takashi Iwai2134ea42008-01-10 16:53:55 +0100358 /* for virtual master */
359 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200360#ifdef CONFIG_SND_HDA_POWER_SAVE
361 struct hda_loopback_check loopback;
362#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200363
364 /* for PLL fix */
365 hda_nid_t pll_nid;
366 unsigned int pll_coef_idx, pll_coef_bit;
Kailang Yangdf694da2005-12-05 19:42:22 +0100367};
368
369/*
370 * configuration template - to be copied to the spec instance
371 */
372struct alc_config_preset {
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200373 struct snd_kcontrol_new *mixers[5]; /* should be identical size
374 * with spec
375 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100376 struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Kailang Yangdf694da2005-12-05 19:42:22 +0100377 const struct hda_verb *init_verbs[5];
378 unsigned int num_dacs;
379 hda_nid_t *dac_nids;
380 hda_nid_t dig_out_nid; /* optional */
381 hda_nid_t hp_nid; /* optional */
Wu Fengguangb25c9da2009-02-06 15:02:27 +0800382 hda_nid_t *slave_dig_outs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100383 unsigned int num_adc_nids;
384 hda_nid_t *adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100385 hda_nid_t *capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +0100386 hda_nid_t dig_in_nid;
387 unsigned int num_channel_mode;
388 const struct hda_channel_mode *channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200389 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200390 int const_channel_count;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200391 unsigned int num_mux_defs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100392 const struct hda_input_mux *input_mux;
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100393 void (*unsol_event)(struct hda_codec *, unsigned int);
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200394 void (*setup)(struct hda_codec *);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100395 void (*init_hook)(struct hda_codec *);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200396#ifdef CONFIG_SND_HDA_POWER_SAVE
397 struct hda_amp_list *loopbacks;
Daniel T Chenc97259d2009-12-27 18:52:08 -0500398 void (*power_hook)(struct hda_codec *codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200399#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400};
401
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
403/*
404 * input MUX handling
405 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200406static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
407 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
409 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
410 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200411 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
412 if (mux_idx >= spec->num_mux_defs)
413 mux_idx = 0;
414 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415}
416
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200417static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419{
420 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
421 struct alc_spec *spec = codec->spec;
422 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
423
424 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
425 return 0;
426}
427
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200428static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
429 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430{
431 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
432 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100433 const struct hda_input_mux *imux;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaicd896c32008-11-18 12:36:33 +0100435 unsigned int mux_idx;
Takashi Iwaie1406342008-02-11 18:32:32 +0100436 hda_nid_t nid = spec->capsrc_nids ?
437 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200438 unsigned int type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Takashi Iwaicd896c32008-11-18 12:36:33 +0100440 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
441 imux = &spec->input_mux[mux_idx];
442
Takashi Iwaia22d5432009-07-27 12:54:26 +0200443 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200444 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100445 /* Matrix-mixer style (e.g. ALC882) */
446 unsigned int *cur_val = &spec->cur_mux[adc_idx];
447 unsigned int i, idx;
448
449 idx = ucontrol->value.enumerated.item[0];
450 if (idx >= imux->num_items)
451 idx = imux->num_items - 1;
452 if (*cur_val == idx)
453 return 0;
454 for (i = 0; i < imux->num_items; i++) {
455 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
456 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
457 imux->items[i].index,
458 HDA_AMP_MUTE, v);
459 }
460 *cur_val = idx;
461 return 1;
462 } else {
463 /* MUX style (e.g. ALC880) */
Takashi Iwaicd896c32008-11-18 12:36:33 +0100464 return snd_hda_input_mux_put(codec, imux, ucontrol, nid,
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100465 &spec->cur_mux[adc_idx]);
466 }
467}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200468
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469/*
470 * channel mode setting
471 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200472static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
473 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
475 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
476 struct alc_spec *spec = codec->spec;
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100477 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
478 spec->num_channel_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479}
480
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200481static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
482 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483{
484 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
485 struct alc_spec *spec = codec->spec;
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100486 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200487 spec->num_channel_mode,
Hector Martin3b315d72009-06-02 10:54:19 +0200488 spec->ext_channel_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489}
490
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200491static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
492 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
494 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
495 struct alc_spec *spec = codec->spec;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200496 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
497 spec->num_channel_mode,
Hector Martin3b315d72009-06-02 10:54:19 +0200498 &spec->ext_channel_count);
499 if (err >= 0 && !spec->const_channel_count) {
500 spec->multiout.max_channels = spec->ext_channel_count;
501 if (spec->need_dac_fix)
502 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
503 }
Takashi Iwai4e195a72006-07-28 14:47:34 +0200504 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505}
506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507/*
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100508 * Control the mode of pin widget settings via the mixer. "pc" is used
Kailang Yangea1fb292008-08-26 12:58:38 +0200509 * instead of "%" to avoid consequences of accidently treating the % as
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100510 * being part of a format specifier. Maximum allowed length of a value is
511 * 63 characters plus NULL terminator.
Jonathan Woithe7cf51e42006-02-09 12:01:26 +0100512 *
513 * Note: some retasking pin complexes seem to ignore requests for input
514 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
515 * are requested. Therefore order this list so that this behaviour will not
516 * cause problems when mixer clients move through the enum sequentially.
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200517 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
518 * March 2006.
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200519 */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100520static char *alc_pin_mode_names[] = {
Jonathan Woithe7cf51e42006-02-09 12:01:26 +0100521 "Mic 50pc bias", "Mic 80pc bias",
522 "Line in", "Line out", "Headphone out",
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100523};
524static unsigned char alc_pin_mode_values[] = {
Jonathan Woithe7cf51e42006-02-09 12:01:26 +0100525 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100526};
527/* The control can present all 5 options, or it can limit the options based
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200528 * in the pin being assumed to be exclusively an input or an output pin. In
529 * addition, "input" pins may or may not process the mic bias option
530 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
531 * accept requests for bias as of chip versions up to March 2006) and/or
532 * wiring in the computer.
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100533 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200534#define ALC_PIN_DIR_IN 0x00
535#define ALC_PIN_DIR_OUT 0x01
536#define ALC_PIN_DIR_INOUT 0x02
537#define ALC_PIN_DIR_IN_NOMICBIAS 0x03
538#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100539
Kailang Yangea1fb292008-08-26 12:58:38 +0200540/* Info about the pin modes supported by the different pin direction modes.
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100541 * For each direction the minimum and maximum values are given.
542 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200543static signed char alc_pin_mode_dir_info[5][2] = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100544 { 0, 2 }, /* ALC_PIN_DIR_IN */
545 { 3, 4 }, /* ALC_PIN_DIR_OUT */
546 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200547 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
548 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100549};
550#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
551#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
552#define alc_pin_mode_n_items(_dir) \
553 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
554
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200555static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
556 struct snd_ctl_elem_info *uinfo)
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200557{
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100558 unsigned int item_num = uinfo->value.enumerated.item;
559 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
560
561 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200562 uinfo->count = 1;
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100563 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
564
565 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
566 item_num = alc_pin_mode_min(dir);
567 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200568 return 0;
569}
570
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200571static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
572 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200573{
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100574 unsigned int i;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200575 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
576 hda_nid_t nid = kcontrol->private_value & 0xffff;
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100577 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200578 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200579 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
580 AC_VERB_GET_PIN_WIDGET_CONTROL,
581 0x00);
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200582
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100583 /* Find enumerated value for current pinctl setting */
584 i = alc_pin_mode_min(dir);
Roel Kluin4b35d2c2009-08-02 13:30:45 +0200585 while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100586 i++;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200587 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100588 return 0;
589}
590
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200591static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
592 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100593{
594 signed int change;
595 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
596 hda_nid_t nid = kcontrol->private_value & 0xffff;
597 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
598 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200599 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
600 AC_VERB_GET_PIN_WIDGET_CONTROL,
601 0x00);
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100602
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200603 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100604 val = alc_pin_mode_min(dir);
605
606 change = pinctl != alc_pin_mode_values[val];
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100607 if (change) {
608 /* Set pin mode to that requested */
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200609 snd_hda_codec_write_cache(codec, nid, 0,
610 AC_VERB_SET_PIN_WIDGET_CONTROL,
611 alc_pin_mode_values[val]);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100612
Kailang Yangea1fb292008-08-26 12:58:38 +0200613 /* Also enable the retasking pin's input/output as required
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100614 * for the requested pin mode. Enum values of 2 or less are
615 * input modes.
616 *
617 * Dynamically switching the input/output buffers probably
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200618 * reduces noise slightly (particularly on input) so we'll
619 * do it. However, having both input and output buffers
620 * enabled simultaneously doesn't seem to be problematic if
621 * this turns out to be necessary in the future.
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100622 */
623 if (val <= 2) {
Takashi Iwai47fd8302007-08-10 17:11:07 +0200624 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
625 HDA_AMP_MUTE, HDA_AMP_MUTE);
626 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
627 HDA_AMP_MUTE, 0);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100628 } else {
Takashi Iwai47fd8302007-08-10 17:11:07 +0200629 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
630 HDA_AMP_MUTE, HDA_AMP_MUTE);
631 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
632 HDA_AMP_MUTE, 0);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100633 }
634 }
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200635 return change;
636}
637
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100638#define ALC_PIN_MODE(xname, nid, dir) \
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200639 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100640 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100641 .info = alc_pin_mode_info, \
642 .get = alc_pin_mode_get, \
643 .put = alc_pin_mode_put, \
644 .private_value = nid | (dir<<16) }
Kailang Yangdf694da2005-12-05 19:42:22 +0100645
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100646/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
647 * together using a mask with more than one bit set. This control is
648 * currently used only by the ALC260 test model. At this stage they are not
649 * needed for any "production" models.
650 */
651#ifdef CONFIG_SND_DEBUG
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200652#define alc_gpio_data_info snd_ctl_boolean_mono_info
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200653
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200654static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
655 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100656{
657 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
658 hda_nid_t nid = kcontrol->private_value & 0xffff;
659 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
660 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200661 unsigned int val = snd_hda_codec_read(codec, nid, 0,
662 AC_VERB_GET_GPIO_DATA, 0x00);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100663
664 *valp = (val & mask) != 0;
665 return 0;
666}
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200667static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
668 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100669{
670 signed int change;
671 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
672 hda_nid_t nid = kcontrol->private_value & 0xffff;
673 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
674 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200675 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
676 AC_VERB_GET_GPIO_DATA,
677 0x00);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100678
679 /* Set/unset the masked GPIO bit(s) as needed */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200680 change = (val == 0 ? 0 : mask) != (gpio_data & mask);
681 if (val == 0)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100682 gpio_data &= ~mask;
683 else
684 gpio_data |= mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200685 snd_hda_codec_write_cache(codec, nid, 0,
686 AC_VERB_SET_GPIO_DATA, gpio_data);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100687
688 return change;
689}
690#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
691 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100692 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100693 .info = alc_gpio_data_info, \
694 .get = alc_gpio_data_get, \
695 .put = alc_gpio_data_put, \
696 .private_value = nid | (mask<<16) }
697#endif /* CONFIG_SND_DEBUG */
698
Jonathan Woithe92621f12006-02-28 11:47:47 +0100699/* A switch control to allow the enabling of the digital IO pins on the
700 * ALC260. This is incredibly simplistic; the intention of this control is
701 * to provide something in the test model allowing digital outputs to be
702 * identified if present. If models are found which can utilise these
703 * outputs a more complete mixer control can be devised for those models if
704 * necessary.
705 */
706#ifdef CONFIG_SND_DEBUG
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200707#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200708
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200709static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
710 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe92621f12006-02-28 11:47:47 +0100711{
712 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
713 hda_nid_t nid = kcontrol->private_value & 0xffff;
714 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
715 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200716 unsigned int val = snd_hda_codec_read(codec, nid, 0,
Andrew Paprocki3982d172007-12-19 12:13:44 +0100717 AC_VERB_GET_DIGI_CONVERT_1, 0x00);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100718
719 *valp = (val & mask) != 0;
720 return 0;
721}
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200722static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
723 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe92621f12006-02-28 11:47:47 +0100724{
725 signed int change;
726 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
727 hda_nid_t nid = kcontrol->private_value & 0xffff;
728 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
729 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200730 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
Andrew Paprocki3982d172007-12-19 12:13:44 +0100731 AC_VERB_GET_DIGI_CONVERT_1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200732 0x00);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100733
734 /* Set/unset the masked control bit(s) as needed */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200735 change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100736 if (val==0)
737 ctrl_data &= ~mask;
738 else
739 ctrl_data |= mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200740 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
741 ctrl_data);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100742
743 return change;
744}
745#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
746 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100747 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe92621f12006-02-28 11:47:47 +0100748 .info = alc_spdif_ctrl_info, \
749 .get = alc_spdif_ctrl_get, \
750 .put = alc_spdif_ctrl_put, \
751 .private_value = nid | (mask<<16) }
752#endif /* CONFIG_SND_DEBUG */
753
Jonathan Woithef8225f62008-01-08 12:16:54 +0100754/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
755 * Again, this is only used in the ALC26x test models to help identify when
756 * the EAPD line must be asserted for features to work.
757 */
758#ifdef CONFIG_SND_DEBUG
759#define alc_eapd_ctrl_info snd_ctl_boolean_mono_info
760
761static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
762 struct snd_ctl_elem_value *ucontrol)
763{
764 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
765 hda_nid_t nid = kcontrol->private_value & 0xffff;
766 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
767 long *valp = ucontrol->value.integer.value;
768 unsigned int val = snd_hda_codec_read(codec, nid, 0,
769 AC_VERB_GET_EAPD_BTLENABLE, 0x00);
770
771 *valp = (val & mask) != 0;
772 return 0;
773}
774
775static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
776 struct snd_ctl_elem_value *ucontrol)
777{
778 int change;
779 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
780 hda_nid_t nid = kcontrol->private_value & 0xffff;
781 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
782 long val = *ucontrol->value.integer.value;
783 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
784 AC_VERB_GET_EAPD_BTLENABLE,
785 0x00);
786
787 /* Set/unset the masked control bit(s) as needed */
788 change = (!val ? 0 : mask) != (ctrl_data & mask);
789 if (!val)
790 ctrl_data &= ~mask;
791 else
792 ctrl_data |= mask;
793 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
794 ctrl_data);
795
796 return change;
797}
798
799#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
800 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100801 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithef8225f62008-01-08 12:16:54 +0100802 .info = alc_eapd_ctrl_info, \
803 .get = alc_eapd_ctrl_get, \
804 .put = alc_eapd_ctrl_put, \
805 .private_value = nid | (mask<<16) }
806#endif /* CONFIG_SND_DEBUG */
807
Kailang Yangdf694da2005-12-05 19:42:22 +0100808/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100809 * set up the input pin config (depending on the given auto-pin type)
810 */
811static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
812 int auto_pin_type)
813{
814 unsigned int val = PIN_IN;
815
816 if (auto_pin_type <= AUTO_PIN_FRONT_MIC) {
817 unsigned int pincap;
Takashi Iwai1327a322009-03-23 13:07:47 +0100818 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100819 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
820 if (pincap & AC_PINCAP_VREF_80)
821 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200822 else if (pincap & AC_PINCAP_VREF_50)
823 val = PIN_VREF50;
824 else if (pincap & AC_PINCAP_VREF_100)
825 val = PIN_VREF100;
826 else if (pincap & AC_PINCAP_VREF_GRD)
827 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100828 }
829 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
830}
831
832/*
Takashi Iwaid88897e2008-10-31 15:01:37 +0100833 */
834static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
835{
836 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
837 return;
838 spec->mixers[spec->num_mixers++] = mix;
839}
840
841static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
842{
843 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
844 return;
845 spec->init_verbs[spec->num_init_verbs++] = verb;
846}
847
848/*
Kailang Yangdf694da2005-12-05 19:42:22 +0100849 * set up from the preset table
850 */
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200851static void setup_preset(struct hda_codec *codec,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200852 const struct alc_config_preset *preset)
Kailang Yangdf694da2005-12-05 19:42:22 +0100853{
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200854 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +0100855 int i;
856
857 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100858 add_mixer(spec, preset->mixers[i]);
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100859 spec->cap_mixer = preset->cap_mixer;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200860 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
861 i++)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100862 add_verb(spec, preset->init_verbs[i]);
Kailang Yangea1fb292008-08-26 12:58:38 +0200863
Kailang Yangdf694da2005-12-05 19:42:22 +0100864 spec->channel_mode = preset->channel_mode;
865 spec->num_channel_mode = preset->num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200866 spec->need_dac_fix = preset->need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200867 spec->const_channel_count = preset->const_channel_count;
Kailang Yangdf694da2005-12-05 19:42:22 +0100868
Hector Martin3b315d72009-06-02 10:54:19 +0200869 if (preset->const_channel_count)
870 spec->multiout.max_channels = preset->const_channel_count;
871 else
872 spec->multiout.max_channels = spec->channel_mode[0].channels;
873 spec->ext_channel_count = spec->channel_mode[0].channels;
Kailang Yangdf694da2005-12-05 19:42:22 +0100874
875 spec->multiout.num_dacs = preset->num_dacs;
876 spec->multiout.dac_nids = preset->dac_nids;
877 spec->multiout.dig_out_nid = preset->dig_out_nid;
Wu Fengguangb25c9da2009-02-06 15:02:27 +0800878 spec->multiout.slave_dig_outs = preset->slave_dig_outs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100879 spec->multiout.hp_nid = preset->hp_nid;
Kailang Yangea1fb292008-08-26 12:58:38 +0200880
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200881 spec->num_mux_defs = preset->num_mux_defs;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200882 if (!spec->num_mux_defs)
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200883 spec->num_mux_defs = 1;
Kailang Yangdf694da2005-12-05 19:42:22 +0100884 spec->input_mux = preset->input_mux;
885
886 spec->num_adc_nids = preset->num_adc_nids;
887 spec->adc_nids = preset->adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100888 spec->capsrc_nids = preset->capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +0100889 spec->dig_in_nid = preset->dig_in_nid;
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100890
891 spec->unsol_event = preset->unsol_event;
892 spec->init_hook = preset->init_hook;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200893#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +0100894 spec->power_hook = preset->power_hook;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200895 spec->loopback.amplist = preset->loopbacks;
896#endif
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200897
898 if (preset->setup)
899 preset->setup(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +0100900}
901
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200902/* Enable GPIO mask and set output */
903static struct hda_verb alc_gpio1_init_verbs[] = {
904 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
905 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
906 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
907 { }
908};
909
910static struct hda_verb alc_gpio2_init_verbs[] = {
911 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
912 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
913 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
914 { }
915};
916
Kailang Yangbdd148a2007-05-08 15:19:08 +0200917static struct hda_verb alc_gpio3_init_verbs[] = {
918 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
919 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
920 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
921 { }
922};
923
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200924/*
925 * Fix hardware PLL issue
926 * On some codecs, the analog PLL gating control must be off while
927 * the default value is 1.
928 */
929static void alc_fix_pll(struct hda_codec *codec)
930{
931 struct alc_spec *spec = codec->spec;
932 unsigned int val;
933
934 if (!spec->pll_nid)
935 return;
936 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
937 spec->pll_coef_idx);
938 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
939 AC_VERB_GET_PROC_COEF, 0);
940 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
941 spec->pll_coef_idx);
942 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
943 val & ~(1 << spec->pll_coef_bit));
944}
945
946static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
947 unsigned int coef_idx, unsigned int coef_bit)
948{
949 struct alc_spec *spec = codec->spec;
950 spec->pll_nid = nid;
951 spec->pll_coef_idx = coef_idx;
952 spec->pll_coef_bit = coef_bit;
953 alc_fix_pll(codec);
954}
955
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200956static void alc_automute_pin(struct hda_codec *codec)
Kailang Yangc9b58002007-10-16 14:30:01 +0200957{
958 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200959 unsigned int nid = spec->autocfg.hp_pins[0];
960 int i;
Kailang Yangc9b58002007-10-16 14:30:01 +0200961
Takashi Iwaiad87c642009-11-02 14:23:15 +0100962 if (!nid)
963 return;
Wu Fengguang864f92b2009-11-18 12:38:02 +0800964 spec->jack_present = snd_hda_jack_detect(codec, nid);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200965 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
966 nid = spec->autocfg.speaker_pins[i];
967 if (!nid)
968 break;
969 snd_hda_codec_write(codec, nid, 0,
970 AC_VERB_SET_PIN_WIDGET_CONTROL,
971 spec->jack_present ? 0 : PIN_OUT);
972 }
Kailang Yangc9b58002007-10-16 14:30:01 +0200973}
974
Takashi Iwai6c819492009-08-10 18:47:44 +0200975static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
976 hda_nid_t nid)
977{
978 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
979 int i, nums;
980
981 nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
982 for (i = 0; i < nums; i++)
983 if (conn[i] == nid)
984 return i;
985 return -1;
986}
987
Kailang Yang7fb0d782008-10-15 11:12:35 +0200988static void alc_mic_automute(struct hda_codec *codec)
989{
990 struct alc_spec *spec = codec->spec;
Takashi Iwai6c819492009-08-10 18:47:44 +0200991 struct alc_mic_route *dead, *alive;
992 unsigned int present, type;
993 hda_nid_t cap_nid;
Kailang Yang7fb0d782008-10-15 11:12:35 +0200994
Takashi Iwaib59bdf32009-08-11 09:47:30 +0200995 if (!spec->auto_mic)
996 return;
Takashi Iwai6c819492009-08-10 18:47:44 +0200997 if (!spec->int_mic.pin || !spec->ext_mic.pin)
998 return;
999 if (snd_BUG_ON(!spec->adc_nids))
1000 return;
1001
1002 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
1003
Wu Fengguang864f92b2009-11-18 12:38:02 +08001004 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
Takashi Iwai6c819492009-08-10 18:47:44 +02001005 if (present) {
1006 alive = &spec->ext_mic;
1007 dead = &spec->int_mic;
1008 } else {
1009 alive = &spec->int_mic;
1010 dead = &spec->ext_mic;
1011 }
1012
Takashi Iwai6c819492009-08-10 18:47:44 +02001013 type = get_wcaps_type(get_wcaps(codec, cap_nid));
1014 if (type == AC_WID_AUD_MIX) {
1015 /* Matrix-mixer style (e.g. ALC882) */
1016 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1017 alive->mux_idx,
1018 HDA_AMP_MUTE, 0);
1019 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1020 dead->mux_idx,
1021 HDA_AMP_MUTE, HDA_AMP_MUTE);
1022 } else {
1023 /* MUX style (e.g. ALC880) */
1024 snd_hda_codec_write_cache(codec, cap_nid, 0,
1025 AC_VERB_SET_CONNECT_SEL,
1026 alive->mux_idx);
1027 }
1028
1029 /* FIXME: analog mixer */
Kailang Yang7fb0d782008-10-15 11:12:35 +02001030}
1031
Kailang Yangc9b58002007-10-16 14:30:01 +02001032/* unsolicited event for HP jack sensing */
1033static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
1034{
1035 if (codec->vendor_id == 0x10ec0880)
1036 res >>= 28;
1037 else
1038 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001039 switch (res) {
1040 case ALC880_HP_EVENT:
1041 alc_automute_pin(codec);
1042 break;
1043 case ALC880_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +02001044 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001045 break;
1046 }
Kailang Yang7fb0d782008-10-15 11:12:35 +02001047}
1048
1049static void alc_inithook(struct hda_codec *codec)
1050{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001051 alc_automute_pin(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +02001052 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +02001053}
1054
Kailang Yangf9423e72008-05-27 12:32:25 +02001055/* additional initialization for ALC888 variants */
1056static void alc888_coef_init(struct hda_codec *codec)
1057{
1058 unsigned int tmp;
1059
1060 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
1061 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1062 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +01001063 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +02001064 /* alc888S-VC */
1065 snd_hda_codec_read(codec, 0x20, 0,
1066 AC_VERB_SET_PROC_COEF, 0x830);
1067 else
1068 /* alc888-VB */
1069 snd_hda_codec_read(codec, 0x20, 0,
1070 AC_VERB_SET_PROC_COEF, 0x3030);
1071}
1072
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02001073static void alc889_coef_init(struct hda_codec *codec)
1074{
1075 unsigned int tmp;
1076
1077 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1078 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1079 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1080 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
1081}
1082
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001083/* turn on/off EAPD control (only if available) */
1084static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
1085{
1086 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
1087 return;
1088 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
1089 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
1090 on ? 2 : 0);
1091}
1092
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001093static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001094{
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001095 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001096
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001097 switch (type) {
1098 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001099 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
1100 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001101 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001102 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
1103 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001104 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001105 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
1106 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001107 case ALC_INIT_DEFAULT:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001108 switch (codec->vendor_id) {
Kailang Yangc9b58002007-10-16 14:30:01 +02001109 case 0x10ec0260:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001110 set_eapd(codec, 0x0f, 1);
1111 set_eapd(codec, 0x10, 1);
Kailang Yangc9b58002007-10-16 14:30:01 +02001112 break;
1113 case 0x10ec0262:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001114 case 0x10ec0267:
1115 case 0x10ec0268:
Kailang Yangc9b58002007-10-16 14:30:01 +02001116 case 0x10ec0269:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001117 case 0x10ec0270:
Takashi Iwaic6e8f2d2009-02-06 12:45:52 +01001118 case 0x10ec0272:
Kailang Yangf9423e72008-05-27 12:32:25 +02001119 case 0x10ec0660:
1120 case 0x10ec0662:
1121 case 0x10ec0663:
Kailang Yangc9b58002007-10-16 14:30:01 +02001122 case 0x10ec0862:
Takashi Iwai20a3a052008-05-23 17:52:53 +02001123 case 0x10ec0889:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001124 set_eapd(codec, 0x14, 1);
1125 set_eapd(codec, 0x15, 1);
Kailang Yangc9b58002007-10-16 14:30:01 +02001126 break;
Kailang Yangbdd148a2007-05-08 15:19:08 +02001127 }
Kailang Yangc9b58002007-10-16 14:30:01 +02001128 switch (codec->vendor_id) {
1129 case 0x10ec0260:
1130 snd_hda_codec_write(codec, 0x1a, 0,
1131 AC_VERB_SET_COEF_INDEX, 7);
1132 tmp = snd_hda_codec_read(codec, 0x1a, 0,
1133 AC_VERB_GET_PROC_COEF, 0);
1134 snd_hda_codec_write(codec, 0x1a, 0,
1135 AC_VERB_SET_COEF_INDEX, 7);
1136 snd_hda_codec_write(codec, 0x1a, 0,
1137 AC_VERB_SET_PROC_COEF,
1138 tmp | 0x2010);
1139 break;
1140 case 0x10ec0262:
1141 case 0x10ec0880:
1142 case 0x10ec0882:
1143 case 0x10ec0883:
1144 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +01001145 case 0x10ec0887:
Takashi Iwai20a3a052008-05-23 17:52:53 +02001146 case 0x10ec0889:
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02001147 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +02001148 break;
Kailang Yangf9423e72008-05-27 12:32:25 +02001149 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001150 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +02001151 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +01001152#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +02001153 case 0x10ec0267:
1154 case 0x10ec0268:
1155 snd_hda_codec_write(codec, 0x20, 0,
1156 AC_VERB_SET_COEF_INDEX, 7);
1157 tmp = snd_hda_codec_read(codec, 0x20, 0,
1158 AC_VERB_GET_PROC_COEF, 0);
1159 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +02001160 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +02001161 snd_hda_codec_write(codec, 0x20, 0,
1162 AC_VERB_SET_PROC_COEF,
1163 tmp | 0x3000);
1164 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +01001165#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001166 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001167 break;
1168 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001169}
Kailang Yangea1fb292008-08-26 12:58:38 +02001170
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001171static void alc_init_auto_hp(struct hda_codec *codec)
1172{
1173 struct alc_spec *spec = codec->spec;
1174
1175 if (!spec->autocfg.hp_pins[0])
Kailang Yangc9b58002007-10-16 14:30:01 +02001176 return;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001177
Kailang Yangc9b58002007-10-16 14:30:01 +02001178 if (!spec->autocfg.speaker_pins[0]) {
Takashi Iwai2a2ed0d2009-04-28 13:01:26 +02001179 if (spec->autocfg.line_out_pins[0] &&
1180 spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
Kailang Yangc9b58002007-10-16 14:30:01 +02001181 spec->autocfg.speaker_pins[0] =
Kailang Yang8c427222008-01-10 13:03:59 +01001182 spec->autocfg.line_out_pins[0];
Kailang Yangc9b58002007-10-16 14:30:01 +02001183 else
1184 return;
1185 }
1186
Takashi Iwai2a2ed0d2009-04-28 13:01:26 +02001187 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
1188 spec->autocfg.hp_pins[0]);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001189 snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0,
1190 AC_VERB_SET_UNSOLICITED_ENABLE,
1191 AC_USRSP_EN | ALC880_HP_EVENT);
1192 spec->unsol_event = alc_sku_unsol_event;
1193}
1194
Takashi Iwai6c819492009-08-10 18:47:44 +02001195static void alc_init_auto_mic(struct hda_codec *codec)
1196{
1197 struct alc_spec *spec = codec->spec;
1198 struct auto_pin_cfg *cfg = &spec->autocfg;
1199 hda_nid_t fixed, ext;
1200 int i;
1201
1202 /* there must be only two mic inputs exclusively */
1203 for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++)
1204 if (cfg->input_pins[i])
1205 return;
1206
1207 fixed = ext = 0;
1208 for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) {
1209 hda_nid_t nid = cfg->input_pins[i];
1210 unsigned int defcfg;
1211 if (!nid)
1212 return;
1213 defcfg = snd_hda_codec_get_pincfg(codec, nid);
1214 switch (get_defcfg_connect(defcfg)) {
1215 case AC_JACK_PORT_FIXED:
1216 if (fixed)
1217 return; /* already occupied */
1218 fixed = nid;
1219 break;
1220 case AC_JACK_PORT_COMPLEX:
1221 if (ext)
1222 return; /* already occupied */
1223 ext = nid;
1224 break;
1225 default:
1226 return; /* invalid entry */
1227 }
1228 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001229 if (!ext || !fixed)
1230 return;
Takashi Iwai6c819492009-08-10 18:47:44 +02001231 if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
1232 return; /* no unsol support */
1233 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
1234 ext, fixed);
1235 spec->ext_mic.pin = ext;
1236 spec->int_mic.pin = fixed;
1237 spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1238 spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1239 spec->auto_mic = 1;
1240 snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
1241 AC_VERB_SET_UNSOLICITED_ENABLE,
1242 AC_USRSP_EN | ALC880_MIC_EVENT);
1243 spec->unsol_event = alc_sku_unsol_event;
1244}
1245
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001246/* check subsystem ID and set up device-specific initialization;
1247 * return 1 if initialized, 0 if invalid SSID
1248 */
1249/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1250 * 31 ~ 16 : Manufacture ID
1251 * 15 ~ 8 : SKU ID
1252 * 7 ~ 0 : Assembly ID
1253 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1254 */
1255static int alc_subsystem_id(struct hda_codec *codec,
1256 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001257 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001258{
1259 unsigned int ass, tmp, i;
1260 unsigned nid;
1261 struct alc_spec *spec = codec->spec;
1262
1263 ass = codec->subsystem_id & 0xffff;
1264 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1265 goto do_sku;
1266
1267 /* invalid SSID, check the special NID pin defcfg instead */
1268 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001269 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001270 * 29~21 : reserve
1271 * 20 : PCBEEP input
1272 * 19~16 : Check sum (15:1)
1273 * 15~1 : Custom
1274 * 0 : override
1275 */
1276 nid = 0x1d;
1277 if (codec->vendor_id == 0x10ec0260)
1278 nid = 0x17;
1279 ass = snd_hda_codec_get_pincfg(codec, nid);
1280 snd_printd("realtek: No valid SSID, "
1281 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001282 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001283 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001284 return 0;
1285 if ((ass >> 30) != 1) /* no physical connection */
1286 return 0;
1287
1288 /* check sum */
1289 tmp = 0;
1290 for (i = 1; i < 16; i++) {
1291 if ((ass >> i) & 1)
1292 tmp++;
1293 }
1294 if (((ass >> 16) & 0xf) != tmp)
1295 return 0;
1296do_sku:
1297 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1298 ass & 0xffff, codec->vendor_id);
1299 /*
1300 * 0 : override
1301 * 1 : Swap Jack
1302 * 2 : 0 --> Desktop, 1 --> Laptop
1303 * 3~5 : External Amplifier control
1304 * 7~6 : Reserved
1305 */
1306 tmp = (ass & 0x38) >> 3; /* external Amp control */
1307 switch (tmp) {
1308 case 1:
1309 spec->init_amp = ALC_INIT_GPIO1;
1310 break;
1311 case 3:
1312 spec->init_amp = ALC_INIT_GPIO2;
1313 break;
1314 case 7:
1315 spec->init_amp = ALC_INIT_GPIO3;
1316 break;
1317 case 5:
1318 spec->init_amp = ALC_INIT_DEFAULT;
1319 break;
1320 }
1321
1322 /* is laptop or Desktop and enable the function "Mute internal speaker
1323 * when the external headphone out jack is plugged"
1324 */
1325 if (!(ass & 0x8000))
1326 return 1;
1327 /*
1328 * 10~8 : Jack location
1329 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1330 * 14~13: Resvered
1331 * 15 : 1 --> enable the function "Mute internal speaker
1332 * when the external headphone out jack is plugged"
1333 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001334 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001335 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001336 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1337 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001338 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001339 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001340 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001341 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001342 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001343 else if (tmp == 3)
1344 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001345 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001346 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001347 for (i = 0; i < spec->autocfg.line_outs; i++)
1348 if (spec->autocfg.line_out_pins[i] == nid)
1349 return 1;
1350 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001351 }
1352
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001353 alc_init_auto_hp(codec);
Takashi Iwai6c819492009-08-10 18:47:44 +02001354 alc_init_auto_mic(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001355 return 1;
1356}
Kailang Yangea1fb292008-08-26 12:58:38 +02001357
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001358static void alc_ssid_check(struct hda_codec *codec,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001359 hda_nid_t porta, hda_nid_t porte,
1360 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001361{
Kailang Yang6227cdc2010-02-25 08:36:52 +01001362 if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001363 struct alc_spec *spec = codec->spec;
1364 snd_printd("realtek: "
1365 "Enable default setup for auto mode as fallback\n");
1366 spec->init_amp = ALC_INIT_DEFAULT;
1367 alc_init_auto_hp(codec);
Takashi Iwai6c819492009-08-10 18:47:44 +02001368 alc_init_auto_mic(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001369 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001370}
1371
Takashi Iwai41e41f12005-06-08 14:48:49 +02001372/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001373 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001374 */
1375
1376struct alc_pincfg {
1377 hda_nid_t nid;
1378 u32 val;
1379};
1380
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001381struct alc_fixup {
1382 const struct alc_pincfg *pins;
1383 const struct hda_verb *verbs;
1384};
1385
1386static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaif95474e2007-07-10 00:47:43 +02001387 const struct snd_pci_quirk *quirk,
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001388 const struct alc_fixup *fix)
Takashi Iwaif95474e2007-07-10 00:47:43 +02001389{
1390 const struct alc_pincfg *cfg;
1391
1392 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1393 if (!quirk)
1394 return;
1395
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001396 fix += quirk->value;
1397 cfg = fix->pins;
1398 if (cfg) {
1399 for (; cfg->nid; cfg++)
1400 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
1401 }
1402 if (fix->verbs)
1403 add_verb(codec->spec, fix->verbs);
Takashi Iwaif95474e2007-07-10 00:47:43 +02001404}
1405
Kailang Yang274693f2009-12-03 10:07:50 +01001406static int alc_read_coef_idx(struct hda_codec *codec,
1407 unsigned int coef_idx)
1408{
1409 unsigned int val;
1410 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1411 coef_idx);
1412 val = snd_hda_codec_read(codec, 0x20, 0,
1413 AC_VERB_GET_PROC_COEF, 0);
1414 return val;
1415}
1416
Takashi Iwaif95474e2007-07-10 00:47:43 +02001417/*
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001418 * ALC888
1419 */
1420
1421/*
1422 * 2ch mode
1423 */
1424static struct hda_verb alc888_4ST_ch2_intel_init[] = {
1425/* Mic-in jack as mic in */
1426 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1427 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1428/* Line-in jack as Line in */
1429 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1430 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1431/* Line-Out as Front */
1432 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1433 { } /* end */
1434};
1435
1436/*
1437 * 4ch mode
1438 */
1439static struct hda_verb alc888_4ST_ch4_intel_init[] = {
1440/* Mic-in jack as mic in */
1441 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1442 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1443/* Line-in jack as Surround */
1444 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1445 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1446/* Line-Out as Front */
1447 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1448 { } /* end */
1449};
1450
1451/*
1452 * 6ch mode
1453 */
1454static struct hda_verb alc888_4ST_ch6_intel_init[] = {
1455/* Mic-in jack as CLFE */
1456 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1457 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1458/* Line-in jack as Surround */
1459 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1460 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1461/* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
1462 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1463 { } /* end */
1464};
1465
1466/*
1467 * 8ch mode
1468 */
1469static struct hda_verb alc888_4ST_ch8_intel_init[] = {
1470/* Mic-in jack as CLFE */
1471 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1472 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1473/* Line-in jack as Surround */
1474 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1475 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1476/* Line-Out as Side */
1477 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1478 { } /* end */
1479};
1480
1481static struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
1482 { 2, alc888_4ST_ch2_intel_init },
1483 { 4, alc888_4ST_ch4_intel_init },
1484 { 6, alc888_4ST_ch6_intel_init },
1485 { 8, alc888_4ST_ch8_intel_init },
1486};
1487
1488/*
1489 * ALC888 Fujitsu Siemens Amillo xa3530
1490 */
1491
1492static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
1493/* Front Mic: set to PIN_IN (empty by default) */
1494 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1495/* Connect Internal HP to Front */
1496 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1497 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1498 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1499/* Connect Bass HP to Front */
1500 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1501 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1502 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1503/* Connect Line-Out side jack (SPDIF) to Side */
1504 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1505 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1506 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1507/* Connect Mic jack to CLFE */
1508 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1509 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1510 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
1511/* Connect Line-in jack to Surround */
1512 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1513 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1514 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
1515/* Connect HP out jack to Front */
1516 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1517 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1518 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1519/* Enable unsolicited event for HP jack and Line-out jack */
1520 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1521 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1522 {}
1523};
1524
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001525static void alc_automute_amp(struct hda_codec *codec)
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001526{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001527 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +08001528 unsigned int mute;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001529 hda_nid_t nid;
1530 int i;
1531
1532 spec->jack_present = 0;
1533 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
1534 nid = spec->autocfg.hp_pins[i];
1535 if (!nid)
1536 break;
Wu Fengguang864f92b2009-11-18 12:38:02 +08001537 if (snd_hda_jack_detect(codec, nid)) {
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001538 spec->jack_present = 1;
1539 break;
1540 }
1541 }
1542
1543 mute = spec->jack_present ? HDA_AMP_MUTE : 0;
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001544 /* Toggle internal speakers muting */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001545 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
1546 nid = spec->autocfg.speaker_pins[i];
1547 if (!nid)
1548 break;
1549 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1550 HDA_AMP_MUTE, mute);
1551 }
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001552}
1553
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001554static void alc_automute_amp_unsol_event(struct hda_codec *codec,
1555 unsigned int res)
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001556{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001557 if (codec->vendor_id == 0x10ec0880)
1558 res >>= 28;
1559 else
1560 res >>= 26;
1561 if (res == ALC880_HP_EVENT)
1562 alc_automute_amp(codec);
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001563}
1564
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001565static void alc889_automute_setup(struct hda_codec *codec)
Wu Fengguang6732bd02009-07-30 09:19:14 +02001566{
1567 struct alc_spec *spec = codec->spec;
1568
1569 spec->autocfg.hp_pins[0] = 0x15;
1570 spec->autocfg.speaker_pins[0] = 0x14;
1571 spec->autocfg.speaker_pins[1] = 0x16;
1572 spec->autocfg.speaker_pins[2] = 0x17;
1573 spec->autocfg.speaker_pins[3] = 0x19;
1574 spec->autocfg.speaker_pins[4] = 0x1a;
Wu Fengguang6732bd02009-07-30 09:19:14 +02001575}
1576
1577static void alc889_intel_init_hook(struct hda_codec *codec)
1578{
1579 alc889_coef_init(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001580 alc_automute_amp(codec);
Wu Fengguang6732bd02009-07-30 09:19:14 +02001581}
1582
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001583static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001584{
1585 struct alc_spec *spec = codec->spec;
1586
1587 spec->autocfg.hp_pins[0] = 0x17; /* line-out */
1588 spec->autocfg.hp_pins[1] = 0x1b; /* hp */
1589 spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
1590 spec->autocfg.speaker_pins[1] = 0x15; /* bass */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001591}
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001592
1593/*
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001594 * ALC888 Acer Aspire 4930G model
1595 */
1596
1597static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
1598/* Front Mic: set to PIN_IN (empty by default) */
1599 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1600/* Unselect Front Mic by default in input mixer 3 */
1601 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001602/* Enable unsolicited event for HP jack */
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001603 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1604/* Connect Internal HP to front */
1605 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1606 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1607 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1608/* Connect HP out to front */
1609 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1610 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1611 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1612 { }
1613};
1614
Hector Martin3b315d72009-06-02 10:54:19 +02001615/*
Tony Vroond2fd4b02009-06-21 00:40:10 +01001616 * ALC888 Acer Aspire 6530G model
1617 */
1618
1619static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
1620/* Bias voltage on for external mic port */
1621 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
Emilio López320d5922009-06-25 08:18:44 +02001622/* Front Mic: set to PIN_IN (empty by default) */
1623 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1624/* Unselect Front Mic by default in input mixer 3 */
1625 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001626/* Enable unsolicited event for HP jack */
1627 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1628/* Enable speaker output */
1629 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1630 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1631/* Enable headphone output */
1632 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
1633 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1634 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1635 { }
1636};
1637
1638/*
Hector Martin018df412009-06-04 00:13:40 +02001639 * ALC889 Acer Aspire 8930G model
Hector Martin3b315d72009-06-02 10:54:19 +02001640 */
1641
Hector Martin018df412009-06-04 00:13:40 +02001642static struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
Hector Martin3b315d72009-06-02 10:54:19 +02001643/* Front Mic: set to PIN_IN (empty by default) */
1644 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1645/* Unselect Front Mic by default in input mixer 3 */
1646 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
1647/* Enable unsolicited event for HP jack */
1648 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1649/* Connect Internal Front to Front */
1650 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1651 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1652 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1653/* Connect Internal Rear to Rear */
1654 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1655 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1656 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
1657/* Connect Internal CLFE to CLFE */
1658 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1659 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1660 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
1661/* Connect HP out to Front */
Hector Martin018df412009-06-04 00:13:40 +02001662 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
Hector Martin3b315d72009-06-02 10:54:19 +02001663 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1664 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1665/* Enable all DACs */
1666/* DAC DISABLE/MUTE 1? */
1667/* setting bits 1-5 disables DAC nids 0x02-0x06 apparently. Init=0x38 */
1668 {0x20, AC_VERB_SET_COEF_INDEX, 0x03},
1669 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
1670/* DAC DISABLE/MUTE 2? */
1671/* some bit here disables the other DACs. Init=0x4900 */
1672 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
1673 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
Hector Martin018df412009-06-04 00:13:40 +02001674/* DMIC fix
1675 * This laptop has a stereo digital microphone. The mics are only 1cm apart
1676 * which makes the stereo useless. However, either the mic or the ALC889
1677 * makes the signal become a difference/sum signal instead of standard
1678 * stereo, which is annoying. So instead we flip this bit which makes the
1679 * codec replicate the sum signal to both channels, turning it into a
1680 * normal mono mic.
1681 */
1682/* DMIC_CONTROL? Init value = 0x0001 */
1683 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
1684 {0x20, AC_VERB_SET_PROC_COEF, 0x0003},
Hector Martin3b315d72009-06-02 10:54:19 +02001685 { }
1686};
1687
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001688static struct hda_input_mux alc888_2_capture_sources[2] = {
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001689 /* Front mic only available on one ADC */
1690 {
1691 .num_items = 4,
1692 .items = {
1693 { "Mic", 0x0 },
1694 { "Line", 0x2 },
1695 { "CD", 0x4 },
1696 { "Front Mic", 0xb },
1697 },
1698 },
1699 {
1700 .num_items = 3,
1701 .items = {
1702 { "Mic", 0x0 },
1703 { "Line", 0x2 },
1704 { "CD", 0x4 },
1705 },
1706 }
1707};
1708
Tony Vroond2fd4b02009-06-21 00:40:10 +01001709static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
1710 /* Interal mic only available on one ADC */
1711 {
Tony Vroon684a8842009-06-26 09:27:50 +01001712 .num_items = 5,
Tony Vroond2fd4b02009-06-21 00:40:10 +01001713 .items = {
1714 { "Ext Mic", 0x0 },
Tony Vroon684a8842009-06-26 09:27:50 +01001715 { "Line In", 0x2 },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001716 { "CD", 0x4 },
Tony Vroon684a8842009-06-26 09:27:50 +01001717 { "Input Mix", 0xa },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001718 { "Int Mic", 0xb },
1719 },
1720 },
1721 {
Tony Vroon684a8842009-06-26 09:27:50 +01001722 .num_items = 4,
Tony Vroond2fd4b02009-06-21 00:40:10 +01001723 .items = {
1724 { "Ext Mic", 0x0 },
Tony Vroon684a8842009-06-26 09:27:50 +01001725 { "Line In", 0x2 },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001726 { "CD", 0x4 },
Tony Vroon684a8842009-06-26 09:27:50 +01001727 { "Input Mix", 0xa },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001728 },
1729 }
1730};
1731
Hector Martin018df412009-06-04 00:13:40 +02001732static struct hda_input_mux alc889_capture_sources[3] = {
1733 /* Digital mic only available on first "ADC" */
1734 {
1735 .num_items = 5,
1736 .items = {
1737 { "Mic", 0x0 },
1738 { "Line", 0x2 },
1739 { "CD", 0x4 },
1740 { "Front Mic", 0xb },
1741 { "Input Mix", 0xa },
1742 },
1743 },
1744 {
1745 .num_items = 4,
1746 .items = {
1747 { "Mic", 0x0 },
1748 { "Line", 0x2 },
1749 { "CD", 0x4 },
1750 { "Input Mix", 0xa },
1751 },
1752 },
1753 {
1754 .num_items = 4,
1755 .items = {
1756 { "Mic", 0x0 },
1757 { "Line", 0x2 },
1758 { "CD", 0x4 },
1759 { "Input Mix", 0xa },
1760 },
1761 }
1762};
1763
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001764static struct snd_kcontrol_new alc888_base_mixer[] = {
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001765 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1766 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1767 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1768 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1769 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
1770 HDA_OUTPUT),
1771 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1772 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1773 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1774 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1775 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1776 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1777 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1778 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1779 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1780 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1781 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
1782 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001783 { } /* end */
1784};
1785
Hector Martin556eea92009-12-20 22:51:23 +01001786static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
1787 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1788 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1789 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1790 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1791 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
1792 HDA_OUTPUT),
1793 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1794 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1795 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1796 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1797 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1798 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1799 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
1800 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1801 { } /* end */
1802};
1803
1804
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001805static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001806{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001807 struct alc_spec *spec = codec->spec;
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001808
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001809 spec->autocfg.hp_pins[0] = 0x15;
1810 spec->autocfg.speaker_pins[0] = 0x14;
Łukasz Wojniłowicz7cef4cf2009-11-20 12:14:35 +01001811 spec->autocfg.speaker_pins[1] = 0x16;
1812 spec->autocfg.speaker_pins[2] = 0x17;
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001813}
1814
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001815static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
Emilio López320d5922009-06-25 08:18:44 +02001816{
1817 struct alc_spec *spec = codec->spec;
1818
1819 spec->autocfg.hp_pins[0] = 0x15;
1820 spec->autocfg.speaker_pins[0] = 0x14;
1821 spec->autocfg.speaker_pins[1] = 0x16;
1822 spec->autocfg.speaker_pins[2] = 0x17;
Emilio López320d5922009-06-25 08:18:44 +02001823}
1824
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001825static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
Hector Martin3b315d72009-06-02 10:54:19 +02001826{
1827 struct alc_spec *spec = codec->spec;
1828
1829 spec->autocfg.hp_pins[0] = 0x15;
1830 spec->autocfg.speaker_pins[0] = 0x14;
1831 spec->autocfg.speaker_pins[1] = 0x16;
1832 spec->autocfg.speaker_pins[2] = 0x1b;
Hector Martin3b315d72009-06-02 10:54:19 +02001833}
1834
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001835/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001836 * ALC880 3-stack model
1837 *
1838 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
Takashi Iwai9c7f8522006-06-28 15:08:22 +02001839 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
1840 * F-Mic = 0x1b, HP = 0x19
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 */
1842
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001843static hda_nid_t alc880_dac_nids[4] = {
1844 /* front, rear, clfe, rear_surr */
1845 0x02, 0x05, 0x04, 0x03
1846};
1847
1848static hda_nid_t alc880_adc_nids[3] = {
1849 /* ADC0-2 */
1850 0x07, 0x08, 0x09,
1851};
1852
1853/* The datasheet says the node 0x07 is connected from inputs,
1854 * but it shows zero connection in the real implementation on some devices.
Kailang Yangdf694da2005-12-05 19:42:22 +01001855 * Note: this is a 915GAV bug, fixed on 915GLV
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001857static hda_nid_t alc880_adc_nids_alt[2] = {
1858 /* ADC1-2 */
1859 0x08, 0x09,
1860};
1861
1862#define ALC880_DIGOUT_NID 0x06
1863#define ALC880_DIGIN_NID 0x0a
1864
1865static struct hda_input_mux alc880_capture_source = {
1866 .num_items = 4,
1867 .items = {
1868 { "Mic", 0x0 },
1869 { "Front Mic", 0x3 },
1870 { "Line", 0x2 },
1871 { "CD", 0x4 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001873};
1874
1875/* channel source setting (2/6 channel selection for 3-stack) */
1876/* 2ch mode */
1877static struct hda_verb alc880_threestack_ch2_init[] = {
1878 /* set line-in to input, mute it */
1879 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1880 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1881 /* set mic-in to input vref 80%, mute it */
1882 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1883 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 { } /* end */
1885};
1886
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001887/* 6ch mode */
1888static struct hda_verb alc880_threestack_ch6_init[] = {
1889 /* set line-in to output, unmute it */
1890 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1891 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1892 /* set mic-in to output, unmute it */
1893 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1894 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1895 { } /* end */
1896};
1897
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01001898static struct hda_channel_mode alc880_threestack_modes[2] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001899 { 2, alc880_threestack_ch2_init },
1900 { 6, alc880_threestack_ch6_init },
1901};
1902
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01001903static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02001904 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01001905 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02001906 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01001907 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02001908 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1909 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01001910 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1911 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1913 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1914 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1915 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1916 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1917 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1918 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
1919 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001921 {
1922 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1923 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01001924 .info = alc_ch_mode_info,
1925 .get = alc_ch_mode_get,
1926 .put = alc_ch_mode_put,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001927 },
1928 { } /* end */
1929};
1930
1931/* capture mixer elements */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001932static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
1933 struct snd_ctl_elem_info *uinfo)
1934{
1935 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1936 struct alc_spec *spec = codec->spec;
1937 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02001938
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001939 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001940 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
1941 HDA_INPUT);
1942 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001943 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001944 return err;
1945}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001947static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1948 unsigned int size, unsigned int __user *tlv)
1949{
1950 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1951 struct alc_spec *spec = codec->spec;
1952 int err;
1953
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001954 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001955 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
1956 HDA_INPUT);
1957 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001958 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001959 return err;
1960}
1961
1962typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
1963 struct snd_ctl_elem_value *ucontrol);
1964
1965static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
1966 struct snd_ctl_elem_value *ucontrol,
1967 getput_call_t func)
1968{
1969 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1970 struct alc_spec *spec = codec->spec;
1971 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1972 int err;
1973
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001974 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001975 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx],
1976 3, 0, HDA_INPUT);
1977 err = func(kcontrol, ucontrol);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08001978 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01001979 return err;
1980}
1981
1982static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
1983 struct snd_ctl_elem_value *ucontrol)
1984{
1985 return alc_cap_getput_caller(kcontrol, ucontrol,
1986 snd_hda_mixer_amp_volume_get);
1987}
1988
1989static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
1990 struct snd_ctl_elem_value *ucontrol)
1991{
1992 return alc_cap_getput_caller(kcontrol, ucontrol,
1993 snd_hda_mixer_amp_volume_put);
1994}
1995
1996/* capture mixer elements */
1997#define alc_cap_sw_info snd_ctl_boolean_stereo_info
1998
1999static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
2000 struct snd_ctl_elem_value *ucontrol)
2001{
2002 return alc_cap_getput_caller(kcontrol, ucontrol,
2003 snd_hda_mixer_amp_switch_get);
2004}
2005
2006static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
2007 struct snd_ctl_elem_value *ucontrol)
2008{
2009 return alc_cap_getput_caller(kcontrol, ucontrol,
2010 snd_hda_mixer_amp_switch_put);
2011}
2012
Takashi Iwaia23b6882009-03-23 15:21:36 +01002013#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002014 { \
2015 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2016 .name = "Capture Switch", \
2017 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
2018 .count = num, \
2019 .info = alc_cap_sw_info, \
2020 .get = alc_cap_sw_get, \
2021 .put = alc_cap_sw_put, \
2022 }, \
2023 { \
2024 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2025 .name = "Capture Volume", \
2026 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2027 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
2028 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
2029 .count = num, \
2030 .info = alc_cap_vol_info, \
2031 .get = alc_cap_vol_get, \
2032 .put = alc_cap_vol_put, \
2033 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01002034 }
2035
2036#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01002037 { \
2038 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2039 /* .name = "Capture Source", */ \
2040 .name = "Input Source", \
2041 .count = num, \
2042 .info = alc_mux_enum_info, \
2043 .get = alc_mux_enum_get, \
2044 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01002045 }
2046
2047#define DEFINE_CAPMIX(num) \
2048static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
2049 _DEFINE_CAPMIX(num), \
2050 _DEFINE_CAPSRC(num), \
2051 { } /* end */ \
2052}
2053
2054#define DEFINE_CAPMIX_NOSRC(num) \
2055static struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
2056 _DEFINE_CAPMIX(num), \
2057 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002058}
2059
2060/* up to three ADCs */
2061DEFINE_CAPMIX(1);
2062DEFINE_CAPMIX(2);
2063DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01002064DEFINE_CAPMIX_NOSRC(1);
2065DEFINE_CAPMIX_NOSRC(2);
2066DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002067
2068/*
2069 * ALC880 5-stack model
2070 *
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002071 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
2072 * Side = 0x02 (0xd)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002073 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
2074 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
2075 */
2076
2077/* additional mixers to alc880_three_stack_mixer */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002078static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002079 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002080 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 { } /* end */
2082};
2083
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002084/* channel source setting (6/8 channel selection for 5-stack) */
2085/* 6ch mode */
2086static struct hda_verb alc880_fivestack_ch6_init[] = {
2087 /* set line-in to input, mute it */
2088 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2089 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002090 { } /* end */
2091};
2092
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002093/* 8ch mode */
2094static struct hda_verb alc880_fivestack_ch8_init[] = {
2095 /* set line-in to output, unmute it */
2096 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2097 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2098 { } /* end */
2099};
2100
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002101static struct hda_channel_mode alc880_fivestack_modes[2] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002102 { 6, alc880_fivestack_ch6_init },
2103 { 8, alc880_fivestack_ch8_init },
2104};
2105
2106
2107/*
2108 * ALC880 6-stack model
2109 *
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002110 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
2111 * Side = 0x05 (0x0f)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002112 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
2113 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
2114 */
2115
2116static hda_nid_t alc880_6st_dac_nids[4] = {
2117 /* front, rear, clfe, rear_surr */
2118 0x02, 0x03, 0x04, 0x05
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002119};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002120
2121static struct hda_input_mux alc880_6stack_capture_source = {
2122 .num_items = 4,
2123 .items = {
2124 { "Mic", 0x0 },
2125 { "Front Mic", 0x1 },
2126 { "Line", 0x2 },
2127 { "CD", 0x4 },
2128 },
2129};
2130
2131/* fixed 8-channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002132static struct hda_channel_mode alc880_sixstack_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002133 { 8, NULL },
2134};
2135
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002136static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002137 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002138 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002139 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002140 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002141 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2142 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002143 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2144 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002145 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002146 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002147 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2148 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2149 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2150 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2151 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2152 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2153 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2154 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002155 {
2156 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2157 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01002158 .info = alc_ch_mode_info,
2159 .get = alc_ch_mode_get,
2160 .put = alc_ch_mode_put,
Takashi Iwai16ded522005-06-10 19:58:24 +02002161 },
2162 { } /* end */
2163};
2164
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002165
2166/*
2167 * ALC880 W810 model
2168 *
2169 * W810 has rear IO for:
2170 * Front (DAC 02)
2171 * Surround (DAC 03)
2172 * Center/LFE (DAC 04)
2173 * Digital out (06)
2174 *
2175 * The system also has a pair of internal speakers, and a headphone jack.
2176 * These are both connected to Line2 on the codec, hence to DAC 02.
Kailang Yangea1fb292008-08-26 12:58:38 +02002177 *
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002178 * There is a variable resistor to control the speaker or headphone
2179 * volume. This is a hardware-only device without a software API.
2180 *
2181 * Plugging headphones in will disable the internal speakers. This is
2182 * implemented in hardware, not via the driver using jack sense. In
2183 * a similar fashion, plugging into the rear socket marked "front" will
2184 * disable both the speakers and headphones.
2185 *
2186 * For input, there's a microphone jack, and an "audio in" jack.
2187 * These may not do anything useful with this driver yet, because I
2188 * haven't setup any initialization verbs for these yet...
2189 */
2190
2191static hda_nid_t alc880_w810_dac_nids[3] = {
2192 /* front, rear/surround, clfe */
2193 0x02, 0x03, 0x04
2194};
2195
2196/* fixed 6 channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002197static struct hda_channel_mode alc880_w810_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002198 { 6, NULL }
2199};
2200
2201/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002202static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002203 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002204 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002205 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002206 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002207 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2208 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002209 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2210 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002211 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2212 { } /* end */
2213};
2214
2215
2216/*
2217 * Z710V model
2218 *
2219 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002220 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
2221 * Line = 0x1a
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002222 */
2223
2224static hda_nid_t alc880_z71v_dac_nids[1] = {
2225 0x02
2226};
2227#define ALC880_Z71V_HP_DAC 0x03
2228
2229/* fixed 2 channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002230static struct hda_channel_mode alc880_2_jack_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002231 { 2, NULL }
2232};
2233
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002234static struct snd_kcontrol_new alc880_z71v_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002235 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002236 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002237 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002238 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002239 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2240 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2241 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2242 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2243 { } /* end */
2244};
2245
2246
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002247/*
2248 * ALC880 F1734 model
2249 *
2250 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
2251 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
2252 */
2253
2254static hda_nid_t alc880_f1734_dac_nids[1] = {
2255 0x03
2256};
2257#define ALC880_F1734_HP_DAC 0x02
2258
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002259static struct snd_kcontrol_new alc880_f1734_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002260 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002261 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01002262 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2263 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002264 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2265 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Takashi Iwai937b4162008-02-11 14:52:36 +01002266 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2267 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002268 { } /* end */
2269};
2270
Takashi Iwai937b4162008-02-11 14:52:36 +01002271static struct hda_input_mux alc880_f1734_capture_source = {
2272 .num_items = 2,
2273 .items = {
2274 { "Mic", 0x1 },
2275 { "CD", 0x4 },
2276 },
2277};
2278
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002279
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002280/*
2281 * ALC880 ASUS model
2282 *
2283 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
2284 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
2285 * Mic = 0x18, Line = 0x1a
2286 */
2287
2288#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
2289#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
2290
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002291static struct snd_kcontrol_new alc880_asus_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002292 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002293 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002294 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002295 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002296 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2297 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002298 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2299 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002300 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2301 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2302 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2303 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2304 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2305 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002306 {
2307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2308 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01002309 .info = alc_ch_mode_info,
2310 .get = alc_ch_mode_get,
2311 .put = alc_ch_mode_put,
Takashi Iwai16ded522005-06-10 19:58:24 +02002312 },
2313 { } /* end */
2314};
2315
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002316/*
2317 * ALC880 ASUS W1V model
2318 *
2319 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
2320 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
2321 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
2322 */
2323
2324/* additional mixers to alc880_asus_mixer */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002325static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002326 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
2327 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002328 { } /* end */
2329};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002330
Kailang Yangdf694da2005-12-05 19:42:22 +01002331/* TCL S700 */
2332static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
2333 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2334 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2335 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
2336 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
2337 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
2338 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
2339 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
2340 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
2341 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01002342 { } /* end */
2343};
2344
Kailang Yangccc656c2006-10-17 12:32:26 +02002345/* Uniwill */
2346static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002347 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2348 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2349 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2350 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002351 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2352 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2353 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2354 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2355 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2356 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2357 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2358 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2359 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2360 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2361 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2362 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002363 {
2364 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2365 .name = "Channel Mode",
2366 .info = alc_ch_mode_info,
2367 .get = alc_ch_mode_get,
2368 .put = alc_ch_mode_put,
2369 },
2370 { } /* end */
2371};
2372
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01002373static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
2374 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2375 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2376 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2377 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
2378 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2379 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2380 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2381 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2382 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2383 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
2384 { } /* end */
2385};
2386
Kailang Yangccc656c2006-10-17 12:32:26 +02002387static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002388 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2389 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2390 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2391 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002392 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2393 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2394 { } /* end */
2395};
2396
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01002398 * virtual master controls
2399 */
2400
2401/*
2402 * slave controls for virtual master
2403 */
2404static const char *alc_slave_vols[] = {
2405 "Front Playback Volume",
2406 "Surround Playback Volume",
2407 "Center Playback Volume",
2408 "LFE Playback Volume",
2409 "Side Playback Volume",
2410 "Headphone Playback Volume",
2411 "Speaker Playback Volume",
2412 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002413 "Line-Out Playback Volume",
Takashi Iwai26f5df22008-11-03 17:39:46 +01002414 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002415 NULL,
2416};
2417
2418static const char *alc_slave_sws[] = {
2419 "Front Playback Switch",
2420 "Surround Playback Switch",
2421 "Center Playback Switch",
2422 "LFE Playback Switch",
2423 "Side Playback Switch",
2424 "Headphone Playback Switch",
2425 "Speaker Playback Switch",
2426 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01002427 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01002428 "Line-Out Playback Switch",
2429 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002430 NULL,
2431};
2432
2433/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002434 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 */
Takashi Iwai603c4012008-07-30 15:01:44 +02002436
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002437#define NID_MAPPING (-1)
2438
2439#define SUBDEV_SPEAKER_ (0 << 6)
2440#define SUBDEV_HP_ (1 << 6)
2441#define SUBDEV_LINE_ (2 << 6)
2442#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
2443#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
2444#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
2445
Takashi Iwai603c4012008-07-30 15:01:44 +02002446static void alc_free_kctls(struct hda_codec *codec);
2447
Takashi Iwai67d634c2009-11-16 15:35:59 +01002448#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002449/* additional beep mixers; the actual parameters are overwritten at build */
2450static struct snd_kcontrol_new alc_beep_mixer[] = {
2451 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002452 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002453 { } /* end */
2454};
Takashi Iwai67d634c2009-11-16 15:35:59 +01002455#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457static int alc_build_controls(struct hda_codec *codec)
2458{
2459 struct alc_spec *spec = codec->spec;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002460 struct snd_kcontrol *kctl;
2461 struct snd_kcontrol_new *knew;
2462 int i, j, err;
2463 unsigned int u;
2464 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
2466 for (i = 0; i < spec->num_mixers; i++) {
2467 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
2468 if (err < 0)
2469 return err;
2470 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002471 if (spec->cap_mixer) {
2472 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
2473 if (err < 0)
2474 return err;
2475 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002477 err = snd_hda_create_spdif_out_ctls(codec,
2478 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 if (err < 0)
2480 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002481 if (!spec->no_analog) {
2482 err = snd_hda_create_spdif_share_sw(codec,
2483 &spec->multiout);
2484 if (err < 0)
2485 return err;
2486 spec->multiout.share_spdif = 1;
2487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 }
2489 if (spec->dig_in_nid) {
2490 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
2491 if (err < 0)
2492 return err;
2493 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01002494
Takashi Iwai67d634c2009-11-16 15:35:59 +01002495#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002496 /* create beep controls if needed */
2497 if (spec->beep_amp) {
2498 struct snd_kcontrol_new *knew;
2499 for (knew = alc_beep_mixer; knew->name; knew++) {
2500 struct snd_kcontrol *kctl;
2501 kctl = snd_ctl_new1(knew, codec);
2502 if (!kctl)
2503 return -ENOMEM;
2504 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002505 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002506 if (err < 0)
2507 return err;
2508 }
2509 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01002510#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002511
Takashi Iwai2134ea42008-01-10 16:53:55 +01002512 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002513 if (!spec->no_analog &&
2514 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002515 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01002516 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002517 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01002518 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002519 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01002520 if (err < 0)
2521 return err;
2522 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002523 if (!spec->no_analog &&
2524 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002525 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
2526 NULL, alc_slave_sws);
2527 if (err < 0)
2528 return err;
2529 }
2530
Takashi Iwai603c4012008-07-30 15:01:44 +02002531 alc_free_kctls(codec); /* no longer needed */
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002532
2533 /* assign Capture Source enums to NID */
2534 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
2535 if (!kctl)
2536 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
2537 for (i = 0; kctl && i < kctl->count; i++) {
Takashi Iwaid1409ae2009-12-17 15:01:31 +01002538 hda_nid_t *nids = spec->capsrc_nids;
2539 if (!nids)
2540 nids = spec->adc_nids;
Takashi Iwai21949f02009-12-23 08:31:59 +01002541 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002542 if (err < 0)
2543 return err;
2544 }
2545 if (spec->cap_mixer) {
2546 const char *kname = kctl ? kctl->id.name : NULL;
2547 for (knew = spec->cap_mixer; knew->name; knew++) {
2548 if (kname && strcmp(knew->name, kname) == 0)
2549 continue;
2550 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
2551 for (i = 0; kctl && i < kctl->count; i++) {
2552 err = snd_hda_add_nid(codec, kctl, i,
2553 spec->adc_nids[i]);
2554 if (err < 0)
2555 return err;
2556 }
2557 }
2558 }
2559
2560 /* other nid->control mapping */
2561 for (i = 0; i < spec->num_mixers; i++) {
2562 for (knew = spec->mixers[i]; knew->name; knew++) {
2563 if (knew->iface != NID_MAPPING)
2564 continue;
2565 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
2566 if (kctl == NULL)
2567 continue;
2568 u = knew->subdevice;
2569 for (j = 0; j < 4; j++, u >>= 8) {
2570 nid = u & 0x3f;
2571 if (nid == 0)
2572 continue;
2573 switch (u & 0xc0) {
2574 case SUBDEV_SPEAKER_:
2575 nid = spec->autocfg.speaker_pins[nid];
2576 break;
2577 case SUBDEV_LINE_:
2578 nid = spec->autocfg.line_out_pins[nid];
2579 break;
2580 case SUBDEV_HP_:
2581 nid = spec->autocfg.hp_pins[nid];
2582 break;
2583 default:
2584 continue;
2585 }
2586 err = snd_hda_add_nid(codec, kctl, 0, nid);
2587 if (err < 0)
2588 return err;
2589 }
2590 u = knew->private_value;
2591 for (j = 0; j < 4; j++, u >>= 8) {
2592 nid = u & 0xff;
2593 if (nid == 0)
2594 continue;
2595 err = snd_hda_add_nid(codec, kctl, 0, nid);
2596 if (err < 0)
2597 return err;
2598 }
2599 }
2600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 return 0;
2602}
2603
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002604
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605/*
2606 * initialize the codec volumes, etc
2607 */
2608
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002609/*
2610 * generic initialization of ADC, input mixers and output mixers
2611 */
2612static struct hda_verb alc880_volume_init_verbs[] = {
2613 /*
2614 * Unmute ADC0-2 and set the default input to mic-in
2615 */
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002616 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002617 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002618 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002619 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002620 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002621 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002623 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2624 * mixer widget
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002625 * Note: PASD motherboards uses the Line In 2 as the input for front
2626 * panel mic (mic 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002628 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02002629 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2630 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2631 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2632 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2633 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2634 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2635 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002637 /*
2638 * Set up output mixers (0x0c - 0x0f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002640 /* set vol=0 to output mixers */
2641 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2642 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2643 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2644 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2645 /* set up input amps for analog loopback */
2646 /* Amp Indices: DAC = 0, mixer = 1 */
Takashi Iwai05acb862005-06-10 19:50:25 +02002647 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2648 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002649 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2650 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002651 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2652 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002653 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2654 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655
2656 { }
2657};
2658
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002659/*
2660 * 3-stack pin configuration:
2661 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
2662 */
2663static struct hda_verb alc880_pin_3stack_init_verbs[] = {
2664 /*
2665 * preset connection lists of input pins
2666 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
2667 */
2668 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
2669 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2670 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
2671
2672 /*
2673 * Set pin mode and muting
2674 */
2675 /* set front pin widgets 0x14 for output */
2676 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2677 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2678 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2679 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2680 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2681 /* Mic2 (as headphone out) for HP output */
2682 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2683 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2684 /* Line In pin widget for input */
2685 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2686 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2687 /* Line2 (as front mic) pin widget for input and vref at 80% */
2688 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2689 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2690 /* CD pin widget for input */
2691 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2692
2693 { }
2694};
2695
2696/*
2697 * 5-stack pin configuration:
2698 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
2699 * line-in/side = 0x1a, f-mic = 0x1b
2700 */
2701static struct hda_verb alc880_pin_5stack_init_verbs[] = {
2702 /*
2703 * preset connection lists of input pins
2704 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
2705 */
2706 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2707 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
2708
2709 /*
2710 * Set pin mode and muting
2711 */
2712 /* set pin widgets 0x14-0x17 for output */
Takashi Iwai05acb862005-06-10 19:50:25 +02002713 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2714 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2715 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2716 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002717 /* unmute pins for output (no gain on this amp) */
2718 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2719 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2720 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2721 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2722
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 /* Mic1 (rear panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02002724 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002725 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2726 /* Mic2 (as headphone out) for HP output */
2727 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai05acb862005-06-10 19:50:25 +02002728 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002729 /* Line In pin widget for input */
2730 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2731 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2732 /* Line2 (as front mic) pin widget for input and vref at 80% */
2733 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2734 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2735 /* CD pin widget for input */
2736 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
2738 { }
2739};
2740
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002741/*
2742 * W810 pin configuration:
2743 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
2744 */
2745static struct hda_verb alc880_pin_w810_init_verbs[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 /* hphone/speaker input selector: front DAC */
2747 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
2748
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002749 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2750 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2751 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2752 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2753 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2754 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2755
2756 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai05acb862005-06-10 19:50:25 +02002757 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 { }
2760};
2761
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002762/*
2763 * Z71V pin configuration:
2764 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
2765 */
2766static struct hda_verb alc880_pin_z71v_init_verbs[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02002767 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002768 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai05acb862005-06-10 19:50:25 +02002769 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002770 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002771
Takashi Iwai16ded522005-06-10 19:58:24 +02002772 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002773 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai16ded522005-06-10 19:58:24 +02002774 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002775 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002776
2777 { }
2778};
2779
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002780/*
2781 * 6-stack pin configuration:
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002782 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
2783 * f-mic = 0x19, line = 0x1a, HP = 0x1b
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002784 */
2785static struct hda_verb alc880_pin_6stack_init_verbs[] = {
2786 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2787
Takashi Iwai16ded522005-06-10 19:58:24 +02002788 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002789 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002790 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002791 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002792 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002793 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002794 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002795 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2796
Takashi Iwai16ded522005-06-10 19:58:24 +02002797 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002798 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002799 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002800 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002801 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002802 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002803 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai16ded522005-06-10 19:58:24 +02002804 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002805 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yangea1fb292008-08-26 12:58:38 +02002806
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002807 { }
2808};
Takashi Iwai16ded522005-06-10 19:58:24 +02002809
Kailang Yangccc656c2006-10-17 12:32:26 +02002810/*
2811 * Uniwill pin configuration:
2812 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
2813 * line = 0x1a
2814 */
2815static struct hda_verb alc880_uniwill_init_verbs[] = {
2816 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2817
2818 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2819 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2820 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2821 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2822 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2823 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2824 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2825 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2826 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2827 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2828 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2829 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2830 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2831 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2832
2833 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2834 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2835 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2836 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2837 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2838 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2839 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
2840 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
2841 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2842
2843 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
2844 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
2845
2846 { }
2847};
2848
2849/*
2850* Uniwill P53
Kailang Yangea1fb292008-08-26 12:58:38 +02002851* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
Kailang Yangccc656c2006-10-17 12:32:26 +02002852 */
2853static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
2854 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2855
2856 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2857 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2858 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2859 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2860 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2861 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2862 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2863 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2864 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2865 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2866 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2867 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2868
2869 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2870 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2871 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2872 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2873 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2874 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2875
2876 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
2877 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
2878
2879 { }
2880};
2881
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01002882static struct hda_verb alc880_beep_init_verbs[] = {
2883 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
2884 { }
2885};
2886
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002887/* auto-toggle front mic */
2888static void alc880_uniwill_mic_automute(struct hda_codec *codec)
2889{
2890 unsigned int present;
2891 unsigned char bits;
Kailang Yangccc656c2006-10-17 12:32:26 +02002892
Wu Fengguang864f92b2009-11-18 12:38:02 +08002893 present = snd_hda_jack_detect(codec, 0x18);
Takashi Iwai47fd8302007-08-10 17:11:07 +02002894 bits = present ? HDA_AMP_MUTE : 0;
2895 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002896}
2897
Takashi Iwai4f5d17062009-08-11 18:17:46 +02002898static void alc880_uniwill_setup(struct hda_codec *codec)
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002899{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002900 struct alc_spec *spec = codec->spec;
2901
2902 spec->autocfg.hp_pins[0] = 0x14;
2903 spec->autocfg.speaker_pins[0] = 0x15;
2904 spec->autocfg.speaker_pins[0] = 0x16;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02002905}
2906
2907static void alc880_uniwill_init_hook(struct hda_codec *codec)
2908{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002909 alc_automute_amp(codec);
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002910 alc880_uniwill_mic_automute(codec);
Kailang Yangccc656c2006-10-17 12:32:26 +02002911}
2912
2913static void alc880_uniwill_unsol_event(struct hda_codec *codec,
2914 unsigned int res)
2915{
2916 /* Looks like the unsol event is incompatible with the standard
2917 * definition. 4bit tag is placed at 28 bit!
2918 */
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002919 switch (res >> 28) {
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002920 case ALC880_MIC_EVENT:
2921 alc880_uniwill_mic_automute(codec);
2922 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002923 default:
2924 alc_automute_amp_unsol_event(codec, res);
2925 break;
Takashi Iwai458a4fa2007-05-05 12:18:40 +02002926 }
Kailang Yangccc656c2006-10-17 12:32:26 +02002927}
2928
Takashi Iwai4f5d17062009-08-11 18:17:46 +02002929static void alc880_uniwill_p53_setup(struct hda_codec *codec)
Kailang Yangccc656c2006-10-17 12:32:26 +02002930{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002931 struct alc_spec *spec = codec->spec;
Kailang Yangccc656c2006-10-17 12:32:26 +02002932
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002933 spec->autocfg.hp_pins[0] = 0x14;
2934 spec->autocfg.speaker_pins[0] = 0x15;
Kailang Yangccc656c2006-10-17 12:32:26 +02002935}
2936
2937static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
2938{
2939 unsigned int present;
Kailang Yangea1fb292008-08-26 12:58:38 +02002940
Kailang Yangccc656c2006-10-17 12:32:26 +02002941 present = snd_hda_codec_read(codec, 0x21, 0,
Takashi Iwai47fd8302007-08-10 17:11:07 +02002942 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
2943 present &= HDA_AMP_VOLMASK;
2944 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
2945 HDA_AMP_VOLMASK, present);
2946 snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
2947 HDA_AMP_VOLMASK, present);
Kailang Yangccc656c2006-10-17 12:32:26 +02002948}
Takashi Iwai47fd8302007-08-10 17:11:07 +02002949
Kailang Yangccc656c2006-10-17 12:32:26 +02002950static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
2951 unsigned int res)
2952{
2953 /* Looks like the unsol event is incompatible with the standard
2954 * definition. 4bit tag is placed at 28 bit!
2955 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002956 if ((res >> 28) == ALC880_DCVOL_EVENT)
Kailang Yangccc656c2006-10-17 12:32:26 +02002957 alc880_uniwill_p53_dcvol_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002958 else
2959 alc_automute_amp_unsol_event(codec, res);
Kailang Yangccc656c2006-10-17 12:32:26 +02002960}
2961
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002962/*
2963 * F1734 pin configuration:
2964 * HP = 0x14, speaker-out = 0x15, mic = 0x18
2965 */
2966static struct hda_verb alc880_pin_f1734_init_verbs[] = {
Michael Gruberee7a9c72008-03-10 11:30:59 +01002967 {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002968 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
2969 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
2970 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
2971 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
2972
2973 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2974 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2975 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2976 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2977
2978 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2979 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Michael Gruberee7a9c72008-03-10 11:30:59 +01002980 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002981 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2982 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2983 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2984 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2985 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2986 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai16ded522005-06-10 19:58:24 +02002987
Takashi Iwai937b4162008-02-11 14:52:36 +01002988 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
2989 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
2990
Takashi Iwai16ded522005-06-10 19:58:24 +02002991 { }
2992};
2993
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002994/*
2995 * ASUS pin configuration:
2996 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
2997 */
2998static struct hda_verb alc880_pin_asus_init_verbs[] = {
2999 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
3000 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
3001 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
3002 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
3003
3004 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3005 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3006 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3007 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3008 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3009 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3010 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3011 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3012
3013 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3014 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3015 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3016 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3017 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3018 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3019 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3020 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3021 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yangea1fb292008-08-26 12:58:38 +02003022
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003023 { }
3024};
3025
3026/* Enable GPIO mask and set output */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003027#define alc880_gpio1_init_verbs alc_gpio1_init_verbs
3028#define alc880_gpio2_init_verbs alc_gpio2_init_verbs
David Heidelberger64a8be72009-06-08 16:15:18 +02003029#define alc880_gpio3_init_verbs alc_gpio3_init_verbs
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003030
Kailang Yangdf694da2005-12-05 19:42:22 +01003031/* Clevo m520g init */
3032static struct hda_verb alc880_pin_clevo_init_verbs[] = {
3033 /* headphone output */
3034 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3035 /* line-out */
3036 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3037 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3038 /* Line-in */
3039 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3040 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3041 /* CD */
3042 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3043 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3044 /* Mic1 (rear panel) */
3045 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3046 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3047 /* Mic2 (front panel) */
3048 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3049 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3050 /* headphone */
3051 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3052 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3053 /* change to EAPD mode */
3054 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3055 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3056
3057 { }
3058};
3059
3060static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
Takashi Iwai4b146cb2006-07-28 14:42:36 +02003061 /* change to EAPD mode */
3062 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3063 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3064
Kailang Yangdf694da2005-12-05 19:42:22 +01003065 /* Headphone output */
3066 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3067 /* Front output*/
3068 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3069 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3070
3071 /* Line In pin widget for input */
3072 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3073 /* CD pin widget for input */
3074 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3075 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3076 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3077
3078 /* change to EAPD mode */
3079 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3080 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
3081
3082 { }
3083};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003084
3085/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003086 * LG m1 express dual
3087 *
3088 * Pin assignment:
3089 * Rear Line-In/Out (blue): 0x14
3090 * Build-in Mic-In: 0x15
3091 * Speaker-out: 0x17
3092 * HP-Out (green): 0x1b
3093 * Mic-In/Out (red): 0x19
3094 * SPDIF-Out: 0x1e
3095 */
3096
3097/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
3098static hda_nid_t alc880_lg_dac_nids[3] = {
3099 0x05, 0x02, 0x03
3100};
3101
3102/* seems analog CD is not working */
3103static struct hda_input_mux alc880_lg_capture_source = {
3104 .num_items = 3,
3105 .items = {
3106 { "Mic", 0x1 },
3107 { "Line", 0x5 },
3108 { "Internal Mic", 0x6 },
3109 },
3110};
3111
3112/* 2,4,6 channel modes */
3113static struct hda_verb alc880_lg_ch2_init[] = {
3114 /* set line-in and mic-in to input */
3115 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
3116 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3117 { }
3118};
3119
3120static struct hda_verb alc880_lg_ch4_init[] = {
3121 /* set line-in to out and mic-in to input */
3122 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3123 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3124 { }
3125};
3126
3127static struct hda_verb alc880_lg_ch6_init[] = {
3128 /* set line-in and mic-in to output */
3129 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3130 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3131 { }
3132};
3133
3134static struct hda_channel_mode alc880_lg_ch_modes[3] = {
3135 { 2, alc880_lg_ch2_init },
3136 { 4, alc880_lg_ch4_init },
3137 { 6, alc880_lg_ch6_init },
3138};
3139
3140static struct snd_kcontrol_new alc880_lg_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01003141 HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3142 HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003143 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3144 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
3145 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
3146 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
3147 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
3148 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
3149 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3150 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3151 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
3152 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
3153 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
3154 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
3155 {
3156 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3157 .name = "Channel Mode",
3158 .info = alc_ch_mode_info,
3159 .get = alc_ch_mode_get,
3160 .put = alc_ch_mode_put,
3161 },
3162 { } /* end */
3163};
3164
3165static struct hda_verb alc880_lg_init_verbs[] = {
3166 /* set capture source to mic-in */
3167 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3168 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3169 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3170 /* mute all amp mixer inputs */
3171 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
Takashi Iwaicb53c622007-08-10 17:21:45 +02003172 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3173 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003174 /* line-in to input */
3175 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3176 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3177 /* built-in mic */
3178 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3179 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3180 /* speaker-out */
3181 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3182 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3183 /* mic-in to input */
3184 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3185 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3186 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3187 /* HP-out */
3188 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
3189 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3190 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3191 /* jack sense */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003192 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003193 { }
3194};
3195
3196/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003197static void alc880_lg_setup(struct hda_codec *codec)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003198{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003199 struct alc_spec *spec = codec->spec;
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003200
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003201 spec->autocfg.hp_pins[0] = 0x1b;
3202 spec->autocfg.speaker_pins[0] = 0x17;
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003203}
3204
3205/*
Takashi Iwaid6815182006-03-23 16:06:23 +01003206 * LG LW20
3207 *
3208 * Pin assignment:
3209 * Speaker-out: 0x14
3210 * Mic-In: 0x18
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003211 * Built-in Mic-In: 0x19
3212 * Line-In: 0x1b
3213 * HP-Out: 0x1a
Takashi Iwaid6815182006-03-23 16:06:23 +01003214 * SPDIF-Out: 0x1e
3215 */
3216
Takashi Iwaid6815182006-03-23 16:06:23 +01003217static struct hda_input_mux alc880_lg_lw_capture_source = {
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003218 .num_items = 3,
Takashi Iwaid6815182006-03-23 16:06:23 +01003219 .items = {
3220 { "Mic", 0x0 },
3221 { "Internal Mic", 0x1 },
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003222 { "Line In", 0x2 },
Takashi Iwaid6815182006-03-23 16:06:23 +01003223 },
3224};
3225
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003226#define alc880_lg_lw_modes alc880_threestack_modes
3227
Takashi Iwaid6815182006-03-23 16:06:23 +01003228static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003229 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3230 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3231 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3232 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
3233 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3234 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3235 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3236 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3237 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3238 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwaid6815182006-03-23 16:06:23 +01003239 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3240 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3241 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
3242 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003243 {
3244 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3245 .name = "Channel Mode",
3246 .info = alc_ch_mode_info,
3247 .get = alc_ch_mode_get,
3248 .put = alc_ch_mode_put,
3249 },
Takashi Iwaid6815182006-03-23 16:06:23 +01003250 { } /* end */
3251};
3252
3253static struct hda_verb alc880_lg_lw_init_verbs[] = {
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003254 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3255 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
3256 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
3257
Takashi Iwaid6815182006-03-23 16:06:23 +01003258 /* set capture source to mic-in */
3259 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3260 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3261 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwaicb53c622007-08-10 17:21:45 +02003262 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Takashi Iwaid6815182006-03-23 16:06:23 +01003263 /* speaker-out */
3264 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3265 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3266 /* HP-out */
Takashi Iwaid6815182006-03-23 16:06:23 +01003267 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3268 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3269 /* mic-in to input */
3270 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3271 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3272 /* built-in mic */
3273 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3274 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3275 /* jack sense */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003276 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaid6815182006-03-23 16:06:23 +01003277 { }
3278};
3279
3280/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003281static void alc880_lg_lw_setup(struct hda_codec *codec)
Takashi Iwaid6815182006-03-23 16:06:23 +01003282{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003283 struct alc_spec *spec = codec->spec;
Takashi Iwaid6815182006-03-23 16:06:23 +01003284
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003285 spec->autocfg.hp_pins[0] = 0x1b;
3286 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwaid6815182006-03-23 16:06:23 +01003287}
3288
Takashi Iwaidf99cd32008-04-25 15:25:04 +02003289static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
3290 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3291 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
3292 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3293 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3294 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3295 HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
3296 { } /* end */
3297};
3298
3299static struct hda_input_mux alc880_medion_rim_capture_source = {
3300 .num_items = 2,
3301 .items = {
3302 { "Mic", 0x0 },
3303 { "Internal Mic", 0x1 },
3304 },
3305};
3306
3307static struct hda_verb alc880_medion_rim_init_verbs[] = {
3308 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3309
3310 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3311 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3312
3313 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3314 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3315 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3316 /* Mic2 (as headphone out) for HP output */
3317 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3318 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3319 /* Internal Speaker */
3320 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3321 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3322
3323 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3324 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3325
3326 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3327 { }
3328};
3329
3330/* toggle speaker-output according to the hp-jack state */
3331static void alc880_medion_rim_automute(struct hda_codec *codec)
3332{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003333 struct alc_spec *spec = codec->spec;
3334 alc_automute_amp(codec);
3335 /* toggle EAPD */
3336 if (spec->jack_present)
Takashi Iwaidf99cd32008-04-25 15:25:04 +02003337 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
3338 else
3339 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
3340}
3341
3342static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
3343 unsigned int res)
3344{
3345 /* Looks like the unsol event is incompatible with the standard
3346 * definition. 4bit tag is placed at 28 bit!
3347 */
3348 if ((res >> 28) == ALC880_HP_EVENT)
3349 alc880_medion_rim_automute(codec);
3350}
3351
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003352static void alc880_medion_rim_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003353{
3354 struct alc_spec *spec = codec->spec;
3355
3356 spec->autocfg.hp_pins[0] = 0x14;
3357 spec->autocfg.speaker_pins[0] = 0x1b;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003358}
3359
Takashi Iwaicb53c622007-08-10 17:21:45 +02003360#ifdef CONFIG_SND_HDA_POWER_SAVE
3361static struct hda_amp_list alc880_loopbacks[] = {
3362 { 0x0b, HDA_INPUT, 0 },
3363 { 0x0b, HDA_INPUT, 1 },
3364 { 0x0b, HDA_INPUT, 2 },
3365 { 0x0b, HDA_INPUT, 3 },
3366 { 0x0b, HDA_INPUT, 4 },
3367 { } /* end */
3368};
3369
3370static struct hda_amp_list alc880_lg_loopbacks[] = {
3371 { 0x0b, HDA_INPUT, 1 },
3372 { 0x0b, HDA_INPUT, 6 },
3373 { 0x0b, HDA_INPUT, 7 },
3374 { } /* end */
3375};
3376#endif
3377
Takashi Iwaid6815182006-03-23 16:06:23 +01003378/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003379 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003380 */
Takashi Iwai16ded522005-06-10 19:58:24 +02003381
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382static int alc_init(struct hda_codec *codec)
3383{
3384 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003385 unsigned int i;
3386
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02003387 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02003388 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02003389
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003390 for (i = 0; i < spec->num_init_verbs; i++)
3391 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003392
3393 if (spec->init_hook)
3394 spec->init_hook(codec);
3395
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 return 0;
3397}
3398
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003399static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
3400{
3401 struct alc_spec *spec = codec->spec;
3402
3403 if (spec->unsol_event)
3404 spec->unsol_event(codec, res);
3405}
3406
Takashi Iwaicb53c622007-08-10 17:21:45 +02003407#ifdef CONFIG_SND_HDA_POWER_SAVE
3408static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
3409{
3410 struct alc_spec *spec = codec->spec;
3411 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
3412}
3413#endif
3414
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415/*
3416 * Analog playback callbacks
3417 */
3418static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
3419 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003420 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421{
3422 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01003423 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
3424 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425}
3426
3427static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3428 struct hda_codec *codec,
3429 unsigned int stream_tag,
3430 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003431 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432{
3433 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003434 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3435 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436}
3437
3438static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3439 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003440 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441{
3442 struct alc_spec *spec = codec->spec;
3443 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3444}
3445
3446/*
3447 * Digital out
3448 */
3449static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3450 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003451 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452{
3453 struct alc_spec *spec = codec->spec;
3454 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3455}
3456
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003457static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3458 struct hda_codec *codec,
3459 unsigned int stream_tag,
3460 unsigned int format,
3461 struct snd_pcm_substream *substream)
3462{
3463 struct alc_spec *spec = codec->spec;
3464 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3465 stream_tag, format, substream);
3466}
3467
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01003468static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3469 struct hda_codec *codec,
3470 struct snd_pcm_substream *substream)
3471{
3472 struct alc_spec *spec = codec->spec;
3473 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
3474}
3475
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
3477 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003478 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479{
3480 struct alc_spec *spec = codec->spec;
3481 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
3482}
3483
3484/*
3485 * Analog capture
3486 */
Takashi Iwai63300792008-01-24 15:31:36 +01003487static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 struct hda_codec *codec,
3489 unsigned int stream_tag,
3490 unsigned int format,
Takashi Iwaic8b6bf9b2005-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
Takashi Iwai63300792008-01-24 15:31:36 +01003495 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 stream_tag, 0, format);
3497 return 0;
3498}
3499
Takashi Iwai63300792008-01-24 15:31:36 +01003500static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003502 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503{
3504 struct alc_spec *spec = codec->spec;
3505
Takashi Iwai888afa12008-03-18 09:57:50 +01003506 snd_hda_codec_cleanup_stream(codec,
3507 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508 return 0;
3509}
3510
3511
3512/*
3513 */
3514static struct hda_pcm_stream alc880_pcm_analog_playback = {
3515 .substreams = 1,
3516 .channels_min = 2,
3517 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003518 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 .ops = {
3520 .open = alc880_playback_pcm_open,
3521 .prepare = alc880_playback_pcm_prepare,
3522 .cleanup = alc880_playback_pcm_cleanup
3523 },
3524};
3525
3526static struct hda_pcm_stream alc880_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01003527 .substreams = 1,
3528 .channels_min = 2,
3529 .channels_max = 2,
3530 /* NID is set in alc_build_pcms */
3531};
3532
3533static struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
3534 .substreams = 1,
3535 .channels_min = 2,
3536 .channels_max = 2,
3537 /* NID is set in alc_build_pcms */
3538};
3539
3540static struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
3541 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542 .channels_min = 2,
3543 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003544 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 .ops = {
Takashi Iwai63300792008-01-24 15:31:36 +01003546 .prepare = alc880_alt_capture_pcm_prepare,
3547 .cleanup = alc880_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 },
3549};
3550
3551static struct hda_pcm_stream alc880_pcm_digital_playback = {
3552 .substreams = 1,
3553 .channels_min = 2,
3554 .channels_max = 2,
3555 /* NID is set in alc_build_pcms */
3556 .ops = {
3557 .open = alc880_dig_playback_pcm_open,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003558 .close = alc880_dig_playback_pcm_close,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01003559 .prepare = alc880_dig_playback_pcm_prepare,
3560 .cleanup = alc880_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561 },
3562};
3563
3564static struct hda_pcm_stream alc880_pcm_digital_capture = {
3565 .substreams = 1,
3566 .channels_min = 2,
3567 .channels_max = 2,
3568 /* NID is set in alc_build_pcms */
3569};
3570
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01003571/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwai63300792008-01-24 15:31:36 +01003572static struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01003573 .substreams = 0,
3574 .channels_min = 0,
3575 .channels_max = 0,
3576};
3577
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578static int alc_build_pcms(struct hda_codec *codec)
3579{
3580 struct alc_spec *spec = codec->spec;
3581 struct hda_pcm *info = spec->pcm_rec;
3582 int i;
3583
3584 codec->num_pcms = 1;
3585 codec->pcm_info = info;
3586
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003587 if (spec->no_analog)
3588 goto skip_analog;
3589
Takashi Iwai812a2cc2009-05-16 10:00:49 +02003590 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
3591 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01003593
Takashi Iwai4a471b72005-12-07 13:56:29 +01003594 if (spec->stream_analog_playback) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003595 if (snd_BUG_ON(!spec->multiout.dac_nids))
3596 return -EINVAL;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003597 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
3598 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
3599 }
3600 if (spec->stream_analog_capture) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003601 if (snd_BUG_ON(!spec->adc_nids))
3602 return -EINVAL;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003603 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
3604 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
3605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606
Takashi Iwai4a471b72005-12-07 13:56:29 +01003607 if (spec->channel_mode) {
3608 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
3609 for (i = 0; i < spec->num_channel_mode; i++) {
3610 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
3611 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
3612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 }
3614 }
3615
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003616 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02003617 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02003619 snprintf(spec->stream_name_digital,
3620 sizeof(spec->stream_name_digital),
3621 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02003622 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08003623 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02003624 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01003626 if (spec->dig_out_type)
3627 info->pcm_type = spec->dig_out_type;
3628 else
3629 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003630 if (spec->multiout.dig_out_nid &&
3631 spec->stream_digital_playback) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
3633 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
3634 }
Takashi Iwai4a471b72005-12-07 13:56:29 +01003635 if (spec->dig_in_nid &&
3636 spec->stream_digital_capture) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
3638 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
3639 }
Takashi Iwai963f8032008-08-11 10:04:40 +02003640 /* FIXME: do we need this for all Realtek codec models? */
3641 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 }
3643
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003644 if (spec->no_analog)
3645 return 0;
3646
Takashi Iwaie08a0072006-09-07 17:52:14 +02003647 /* If the use of more than one ADC is requested for the current
3648 * model, configure a second analog capture-only PCM.
3649 */
3650 /* Additional Analaog capture for index #2 */
Takashi Iwai63300792008-01-24 15:31:36 +01003651 if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||
3652 (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02003653 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02003654 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02003655 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01003656 if (spec->alt_dac_nid) {
3657 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3658 *spec->stream_analog_alt_playback;
3659 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
3660 spec->alt_dac_nid;
3661 } else {
3662 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3663 alc_pcm_null_stream;
3664 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
3665 }
3666 if (spec->num_adc_nids > 1) {
3667 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3668 *spec->stream_analog_alt_capture;
3669 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
3670 spec->adc_nids[1];
3671 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
3672 spec->num_adc_nids - 1;
3673 } else {
3674 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3675 alc_pcm_null_stream;
3676 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02003677 }
3678 }
3679
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 return 0;
3681}
3682
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003683static inline void alc_shutup(struct hda_codec *codec)
3684{
3685 snd_hda_shutup_pins(codec);
3686}
3687
Takashi Iwai603c4012008-07-30 15:01:44 +02003688static void alc_free_kctls(struct hda_codec *codec)
3689{
3690 struct alc_spec *spec = codec->spec;
3691
3692 if (spec->kctls.list) {
3693 struct snd_kcontrol_new *kctl = spec->kctls.list;
3694 int i;
3695 for (i = 0; i < spec->kctls.used; i++)
3696 kfree(kctl[i].name);
3697 }
3698 snd_array_free(&spec->kctls);
3699}
3700
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701static void alc_free(struct hda_codec *codec)
3702{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003703 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003704
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02003705 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003706 return;
3707
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003708 alc_shutup(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02003709 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003710 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09003711 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712}
3713
Hector Martinf5de24b2009-12-20 22:51:31 +01003714#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05003715static void alc_power_eapd(struct hda_codec *codec)
3716{
3717 /* We currently only handle front, HP */
3718 switch (codec->vendor_id) {
3719 case 0x10ec0260:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003720 set_eapd(codec, 0x0f, 0);
3721 set_eapd(codec, 0x10, 0);
Daniel T Chenc97259d2009-12-27 18:52:08 -05003722 break;
3723 case 0x10ec0262:
3724 case 0x10ec0267:
3725 case 0x10ec0268:
3726 case 0x10ec0269:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003727 case 0x10ec0270:
Daniel T Chenc97259d2009-12-27 18:52:08 -05003728 case 0x10ec0272:
3729 case 0x10ec0660:
3730 case 0x10ec0662:
3731 case 0x10ec0663:
3732 case 0x10ec0862:
3733 case 0x10ec0889:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003734 set_eapd(codec, 0x14, 0);
3735 set_eapd(codec, 0x15, 0);
Daniel T Chenc97259d2009-12-27 18:52:08 -05003736 break;
3737 }
3738}
3739
Hector Martinf5de24b2009-12-20 22:51:31 +01003740static int alc_suspend(struct hda_codec *codec, pm_message_t state)
3741{
3742 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003743 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01003744 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05003745 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01003746 return 0;
3747}
3748#endif
3749
Takashi Iwaie044c392008-10-27 16:56:24 +01003750#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaie044c392008-10-27 16:56:24 +01003751static int alc_resume(struct hda_codec *codec)
3752{
Takashi Iwaie044c392008-10-27 16:56:24 +01003753 codec->patch_ops.init(codec);
3754 snd_hda_codec_resume_amp(codec);
3755 snd_hda_codec_resume_cache(codec);
3756 return 0;
3757}
Takashi Iwaie044c392008-10-27 16:56:24 +01003758#endif
3759
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760/*
3761 */
3762static struct hda_codec_ops alc_patch_ops = {
3763 .build_controls = alc_build_controls,
3764 .build_pcms = alc_build_pcms,
3765 .init = alc_init,
3766 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003767 .unsol_event = alc_unsol_event,
Takashi Iwaie044c392008-10-27 16:56:24 +01003768#ifdef SND_HDA_NEEDS_RESUME
3769 .resume = alc_resume,
3770#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02003771#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01003772 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02003773 .check_power_status = alc_check_power_status,
3774#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05003775 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776};
3777
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003778
3779/*
3780 * Test configuration for debugging
3781 *
3782 * Almost all inputs/outputs are enabled. I/O pins can be configured via
3783 * enum controls.
3784 */
3785#ifdef CONFIG_SND_DEBUG
3786static hda_nid_t alc880_test_dac_nids[4] = {
3787 0x02, 0x03, 0x04, 0x05
3788};
3789
3790static struct hda_input_mux alc880_test_capture_source = {
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003791 .num_items = 7,
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003792 .items = {
3793 { "In-1", 0x0 },
3794 { "In-2", 0x1 },
3795 { "In-3", 0x2 },
3796 { "In-4", 0x3 },
3797 { "CD", 0x4 },
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003798 { "Front", 0x5 },
3799 { "Surround", 0x6 },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003800 },
3801};
3802
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01003803static struct hda_channel_mode alc880_test_modes[4] = {
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003804 { 2, NULL },
Takashi Iwaifd2c3262005-05-13 17:18:42 +02003805 { 4, NULL },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003806 { 6, NULL },
Takashi Iwaifd2c3262005-05-13 17:18:42 +02003807 { 8, NULL },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003808};
3809
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003810static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
3811 struct snd_ctl_elem_info *uinfo)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003812{
3813 static char *texts[] = {
3814 "N/A", "Line Out", "HP Out",
3815 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
3816 };
3817 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3818 uinfo->count = 1;
3819 uinfo->value.enumerated.items = 8;
3820 if (uinfo->value.enumerated.item >= 8)
3821 uinfo->value.enumerated.item = 7;
3822 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3823 return 0;
3824}
3825
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003826static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
3827 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003828{
3829 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3830 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
3831 unsigned int pin_ctl, item = 0;
3832
3833 pin_ctl = snd_hda_codec_read(codec, nid, 0,
3834 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3835 if (pin_ctl & AC_PINCTL_OUT_EN) {
3836 if (pin_ctl & AC_PINCTL_HP_EN)
3837 item = 2;
3838 else
3839 item = 1;
3840 } else if (pin_ctl & AC_PINCTL_IN_EN) {
3841 switch (pin_ctl & AC_PINCTL_VREFEN) {
3842 case AC_PINCTL_VREF_HIZ: item = 3; break;
3843 case AC_PINCTL_VREF_50: item = 4; break;
3844 case AC_PINCTL_VREF_GRD: item = 5; break;
3845 case AC_PINCTL_VREF_80: item = 6; break;
3846 case AC_PINCTL_VREF_100: item = 7; break;
3847 }
3848 }
3849 ucontrol->value.enumerated.item[0] = item;
3850 return 0;
3851}
3852
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003853static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
3854 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003855{
3856 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3857 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
3858 static unsigned int ctls[] = {
3859 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
3860 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
3861 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
3862 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
3863 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
3864 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
3865 };
3866 unsigned int old_ctl, new_ctl;
3867
3868 old_ctl = snd_hda_codec_read(codec, nid, 0,
3869 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3870 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
3871 if (old_ctl != new_ctl) {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003872 int val;
3873 snd_hda_codec_write_cache(codec, nid, 0,
3874 AC_VERB_SET_PIN_WIDGET_CONTROL,
3875 new_ctl);
Takashi Iwai47fd8302007-08-10 17:11:07 +02003876 val = ucontrol->value.enumerated.item[0] >= 3 ?
3877 HDA_AMP_MUTE : 0;
3878 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
3879 HDA_AMP_MUTE, val);
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003880 return 1;
3881 }
3882 return 0;
3883}
3884
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003885static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
3886 struct snd_ctl_elem_info *uinfo)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003887{
3888 static char *texts[] = {
3889 "Front", "Surround", "CLFE", "Side"
3890 };
3891 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3892 uinfo->count = 1;
3893 uinfo->value.enumerated.items = 4;
3894 if (uinfo->value.enumerated.item >= 4)
3895 uinfo->value.enumerated.item = 3;
3896 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3897 return 0;
3898}
3899
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003900static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
3901 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003902{
3903 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3904 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
3905 unsigned int sel;
3906
3907 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
3908 ucontrol->value.enumerated.item[0] = sel & 3;
3909 return 0;
3910}
3911
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003912static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
3913 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003914{
3915 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3916 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
3917 unsigned int sel;
3918
3919 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
3920 if (ucontrol->value.enumerated.item[0] != sel) {
3921 sel = ucontrol->value.enumerated.item[0] & 3;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02003922 snd_hda_codec_write_cache(codec, nid, 0,
3923 AC_VERB_SET_CONNECT_SEL, sel);
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003924 return 1;
3925 }
3926 return 0;
3927}
3928
3929#define PIN_CTL_TEST(xname,nid) { \
3930 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3931 .name = xname, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01003932 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003933 .info = alc_test_pin_ctl_info, \
3934 .get = alc_test_pin_ctl_get, \
3935 .put = alc_test_pin_ctl_put, \
3936 .private_value = nid \
3937 }
3938
3939#define PIN_SRC_TEST(xname,nid) { \
3940 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3941 .name = xname, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01003942 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003943 .info = alc_test_pin_src_info, \
3944 .get = alc_test_pin_src_get, \
3945 .put = alc_test_pin_src_put, \
3946 .private_value = nid \
3947 }
3948
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003949static struct snd_kcontrol_new alc880_test_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02003950 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3951 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
3952 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
3953 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01003954 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3955 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
3956 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
3957 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003958 PIN_CTL_TEST("Front Pin Mode", 0x14),
3959 PIN_CTL_TEST("Surround Pin Mode", 0x15),
3960 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
3961 PIN_CTL_TEST("Side Pin Mode", 0x17),
3962 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
3963 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
3964 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
3965 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
3966 PIN_SRC_TEST("In-1 Pin Source", 0x18),
3967 PIN_SRC_TEST("In-2 Pin Source", 0x19),
3968 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
3969 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
3970 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
3971 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
3972 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
3973 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
3974 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
3975 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
3976 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
3977 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
3978 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
3979 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003980 {
3981 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3982 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01003983 .info = alc_ch_mode_info,
3984 .get = alc_ch_mode_get,
3985 .put = alc_ch_mode_put,
Takashi Iwai2fa522b2005-05-12 14:51:12 +02003986 },
3987 { } /* end */
3988};
3989
3990static struct hda_verb alc880_test_init_verbs[] = {
3991 /* Unmute inputs of 0x0c - 0x0f */
Takashi Iwai05acb862005-06-10 19:50:25 +02003992 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3993 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3994 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3995 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3996 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3997 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3998 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3999 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004000 /* Vol output for 0x0c-0x0f */
Takashi Iwai05acb862005-06-10 19:50:25 +02004001 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4002 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4003 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4004 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004005 /* Set output pins 0x14-0x17 */
Takashi Iwai05acb862005-06-10 19:50:25 +02004006 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4007 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4008 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4009 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004010 /* Unmute output pins 0x14-0x17 */
Takashi Iwai05acb862005-06-10 19:50:25 +02004011 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4012 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4013 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4014 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004015 /* Set input pins 0x18-0x1c */
Takashi Iwai16ded522005-06-10 19:58:24 +02004016 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4017 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwai05acb862005-06-10 19:50:25 +02004018 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4019 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4020 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004021 /* Mute input pins 0x18-0x1b */
Takashi Iwai05acb862005-06-10 19:50:25 +02004022 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4023 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4024 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4025 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004026 /* ADC set up */
Takashi Iwai05acb862005-06-10 19:50:25 +02004027 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004028 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004029 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004030 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004031 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004032 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004033 /* Analog input/passthru */
4034 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4035 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4036 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4037 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4038 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004039 { }
4040};
4041#endif
4042
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043/*
4044 */
4045
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004046static const char *alc880_models[ALC880_MODEL_LAST] = {
4047 [ALC880_3ST] = "3stack",
4048 [ALC880_TCL_S700] = "tcl",
4049 [ALC880_3ST_DIG] = "3stack-digout",
4050 [ALC880_CLEVO] = "clevo",
4051 [ALC880_5ST] = "5stack",
4052 [ALC880_5ST_DIG] = "5stack-digout",
4053 [ALC880_W810] = "w810",
4054 [ALC880_Z71V] = "z71v",
4055 [ALC880_6ST] = "6stack",
4056 [ALC880_6ST_DIG] = "6stack-digout",
4057 [ALC880_ASUS] = "asus",
4058 [ALC880_ASUS_W1V] = "asus-w1v",
4059 [ALC880_ASUS_DIG] = "asus-dig",
4060 [ALC880_ASUS_DIG2] = "asus-dig2",
4061 [ALC880_UNIWILL_DIG] = "uniwill",
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004062 [ALC880_UNIWILL_P53] = "uniwill-p53",
4063 [ALC880_FUJITSU] = "fujitsu",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004064 [ALC880_F1734] = "F1734",
4065 [ALC880_LG] = "lg",
4066 [ALC880_LG_LW] = "lg-lw",
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004067 [ALC880_MEDION_RIM] = "medion",
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004068#ifdef CONFIG_SND_DEBUG
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004069 [ALC880_TEST] = "test",
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004070#endif
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004071 [ALC880_AUTO] = "auto",
4072};
4073
4074static struct snd_pci_quirk alc880_cfg_tbl[] = {
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004075 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004076 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
4077 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
4078 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
4079 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
4080 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
4081 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
4082 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
4083 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004084 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
4085 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004086 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
4087 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
4088 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
4089 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
4090 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
4091 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
4092 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
4093 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
4094 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
4095 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
Travis Place186c3112008-05-20 11:54:41 +02004096 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004097 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
4098 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
4099 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
Takashi Iwaidea0a502009-02-09 17:14:52 +01004100 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004101 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004102 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
4103 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004104 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
4105 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004106 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
4107 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
4108 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
4109 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004110 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
4111 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004112 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004113 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004114 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004115 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004116 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
4117 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004118 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004119 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004120 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004121 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004122 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
Travis Place1d116042008-06-23 11:42:30 +02004123 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004124 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004125 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004126 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004127 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
4128 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004129 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004130 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
4131 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
4132 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
4133 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004134 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
4135 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004136 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004137 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004138 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
4139 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004140 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
4141 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
4142 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +01004143 /* default Intel */
4144 SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004145 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
4146 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 {}
4148};
4149
Takashi Iwai16ded522005-06-10 19:58:24 +02004150/*
Kailang Yangdf694da2005-12-05 19:42:22 +01004151 * ALC880 codec presets
Takashi Iwai16ded522005-06-10 19:58:24 +02004152 */
Takashi Iwai16ded522005-06-10 19:58:24 +02004153static struct alc_config_preset alc880_presets[] = {
4154 [ALC880_3ST] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004155 .mixers = { alc880_three_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004156 .init_verbs = { alc880_volume_init_verbs,
4157 alc880_pin_3stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004158 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwai16ded522005-06-10 19:58:24 +02004159 .dac_nids = alc880_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004160 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4161 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004162 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004163 .input_mux = &alc880_capture_source,
4164 },
4165 [ALC880_3ST_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004166 .mixers = { alc880_three_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004167 .init_verbs = { alc880_volume_init_verbs,
4168 alc880_pin_3stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004169 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwai16ded522005-06-10 19:58:24 +02004170 .dac_nids = alc880_dac_nids,
4171 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004172 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4173 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004174 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004175 .input_mux = &alc880_capture_source,
4176 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004177 [ALC880_TCL_S700] = {
4178 .mixers = { alc880_tcl_s700_mixer },
4179 .init_verbs = { alc880_volume_init_verbs,
4180 alc880_pin_tcl_S700_init_verbs,
4181 alc880_gpio2_init_verbs },
4182 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4183 .dac_nids = alc880_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01004184 .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
4185 .num_adc_nids = 1, /* single ADC */
Kailang Yangdf694da2005-12-05 19:42:22 +01004186 .hp_nid = 0x03,
4187 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4188 .channel_mode = alc880_2_jack_modes,
4189 .input_mux = &alc880_capture_source,
4190 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004191 [ALC880_5ST] = {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004192 .mixers = { alc880_three_stack_mixer,
4193 alc880_five_stack_mixer},
4194 .init_verbs = { alc880_volume_init_verbs,
4195 alc880_pin_5stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004196 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4197 .dac_nids = alc880_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004198 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
4199 .channel_mode = alc880_fivestack_modes,
4200 .input_mux = &alc880_capture_source,
4201 },
4202 [ALC880_5ST_DIG] = {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004203 .mixers = { alc880_three_stack_mixer,
4204 alc880_five_stack_mixer },
4205 .init_verbs = { alc880_volume_init_verbs,
4206 alc880_pin_5stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004207 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4208 .dac_nids = alc880_dac_nids,
4209 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004210 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
4211 .channel_mode = alc880_fivestack_modes,
4212 .input_mux = &alc880_capture_source,
4213 },
Takashi Iwaib6482d42005-06-27 15:32:43 +02004214 [ALC880_6ST] = {
4215 .mixers = { alc880_six_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004216 .init_verbs = { alc880_volume_init_verbs,
4217 alc880_pin_6stack_init_verbs },
Takashi Iwaib6482d42005-06-27 15:32:43 +02004218 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
4219 .dac_nids = alc880_6st_dac_nids,
4220 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
4221 .channel_mode = alc880_sixstack_modes,
4222 .input_mux = &alc880_6stack_capture_source,
4223 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004224 [ALC880_6ST_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004225 .mixers = { alc880_six_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004226 .init_verbs = { alc880_volume_init_verbs,
4227 alc880_pin_6stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004228 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
4229 .dac_nids = alc880_6st_dac_nids,
4230 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004231 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
4232 .channel_mode = alc880_sixstack_modes,
4233 .input_mux = &alc880_6stack_capture_source,
4234 },
4235 [ALC880_W810] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004236 .mixers = { alc880_w810_base_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004237 .init_verbs = { alc880_volume_init_verbs,
4238 alc880_pin_w810_init_verbs,
Takashi Iwaib0af0de2005-06-21 14:49:19 +02004239 alc880_gpio2_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004240 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
4241 .dac_nids = alc880_w810_dac_nids,
4242 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004243 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
4244 .channel_mode = alc880_w810_modes,
4245 .input_mux = &alc880_capture_source,
4246 },
4247 [ALC880_Z71V] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004248 .mixers = { alc880_z71v_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004249 .init_verbs = { alc880_volume_init_verbs,
4250 alc880_pin_z71v_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004251 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
4252 .dac_nids = alc880_z71v_dac_nids,
4253 .dig_out_nid = ALC880_DIGOUT_NID,
4254 .hp_nid = 0x03,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004255 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4256 .channel_mode = alc880_2_jack_modes,
Takashi Iwai16ded522005-06-10 19:58:24 +02004257 .input_mux = &alc880_capture_source,
4258 },
4259 [ALC880_F1734] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004260 .mixers = { alc880_f1734_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004261 .init_verbs = { alc880_volume_init_verbs,
4262 alc880_pin_f1734_init_verbs },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004263 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
4264 .dac_nids = alc880_f1734_dac_nids,
4265 .hp_nid = 0x02,
4266 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4267 .channel_mode = alc880_2_jack_modes,
Takashi Iwai937b4162008-02-11 14:52:36 +01004268 .input_mux = &alc880_f1734_capture_source,
4269 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004270 .setup = alc880_uniwill_p53_setup,
4271 .init_hook = alc_automute_amp,
Takashi Iwai16ded522005-06-10 19:58:24 +02004272 },
4273 [ALC880_ASUS] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004274 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004275 .init_verbs = { alc880_volume_init_verbs,
4276 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004277 alc880_gpio1_init_verbs },
4278 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4279 .dac_nids = alc880_asus_dac_nids,
4280 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4281 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004282 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004283 .input_mux = &alc880_capture_source,
4284 },
4285 [ALC880_ASUS_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004286 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004287 .init_verbs = { alc880_volume_init_verbs,
4288 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004289 alc880_gpio1_init_verbs },
4290 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4291 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004292 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004293 .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 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004298 [ALC880_ASUS_DIG2] = {
4299 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004300 .init_verbs = { alc880_volume_init_verbs,
4301 alc880_pin_asus_init_verbs,
Kailang Yangdf694da2005-12-05 19:42:22 +01004302 alc880_gpio2_init_verbs }, /* use GPIO2 */
4303 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4304 .dac_nids = alc880_asus_dac_nids,
4305 .dig_out_nid = ALC880_DIGOUT_NID,
4306 .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,
Kailang Yangdf694da2005-12-05 19:42:22 +01004309 .input_mux = &alc880_capture_source,
4310 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004311 [ALC880_ASUS_W1V] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004312 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004313 .init_verbs = { alc880_volume_init_verbs,
4314 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004315 alc880_gpio1_init_verbs },
4316 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4317 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004318 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004319 .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,
Takashi Iwai16ded522005-06-10 19:58:24 +02004322 .input_mux = &alc880_capture_source,
4323 },
4324 [ALC880_UNIWILL_DIG] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01004325 .mixers = { alc880_asus_mixer },
Kailang Yangccc656c2006-10-17 12:32:26 +02004326 .init_verbs = { alc880_volume_init_verbs,
4327 alc880_pin_asus_init_verbs },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004328 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4329 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004330 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004331 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4332 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004333 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004334 .input_mux = &alc880_capture_source,
4335 },
Kailang Yangccc656c2006-10-17 12:32:26 +02004336 [ALC880_UNIWILL] = {
4337 .mixers = { alc880_uniwill_mixer },
4338 .init_verbs = { alc880_volume_init_verbs,
4339 alc880_uniwill_init_verbs },
4340 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4341 .dac_nids = alc880_asus_dac_nids,
4342 .dig_out_nid = ALC880_DIGOUT_NID,
4343 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4344 .channel_mode = alc880_threestack_modes,
4345 .need_dac_fix = 1,
4346 .input_mux = &alc880_capture_source,
4347 .unsol_event = alc880_uniwill_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004348 .setup = alc880_uniwill_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004349 .init_hook = alc880_uniwill_init_hook,
Kailang Yangccc656c2006-10-17 12:32:26 +02004350 },
4351 [ALC880_UNIWILL_P53] = {
4352 .mixers = { alc880_uniwill_p53_mixer },
4353 .init_verbs = { alc880_volume_init_verbs,
4354 alc880_uniwill_p53_init_verbs },
4355 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4356 .dac_nids = alc880_asus_dac_nids,
4357 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004358 .channel_mode = alc880_threestack_modes,
4359 .input_mux = &alc880_capture_source,
4360 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004361 .setup = alc880_uniwill_p53_setup,
4362 .init_hook = alc_automute_amp,
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004363 },
4364 [ALC880_FUJITSU] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01004365 .mixers = { alc880_fujitsu_mixer },
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004366 .init_verbs = { alc880_volume_init_verbs,
4367 alc880_uniwill_p53_init_verbs,
4368 alc880_beep_init_verbs },
4369 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4370 .dac_nids = alc880_dac_nids,
Takashi Iwaid53d7d92007-08-20 15:20:02 +02004371 .dig_out_nid = ALC880_DIGOUT_NID,
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004372 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4373 .channel_mode = alc880_2_jack_modes,
Kailang Yangccc656c2006-10-17 12:32:26 +02004374 .input_mux = &alc880_capture_source,
4375 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004376 .setup = alc880_uniwill_p53_setup,
4377 .init_hook = alc_automute_amp,
Kailang Yangccc656c2006-10-17 12:32:26 +02004378 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004379 [ALC880_CLEVO] = {
4380 .mixers = { alc880_three_stack_mixer },
4381 .init_verbs = { alc880_volume_init_verbs,
4382 alc880_pin_clevo_init_verbs },
4383 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4384 .dac_nids = alc880_dac_nids,
4385 .hp_nid = 0x03,
4386 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4387 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004388 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +01004389 .input_mux = &alc880_capture_source,
4390 },
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004391 [ALC880_LG] = {
4392 .mixers = { alc880_lg_mixer },
4393 .init_verbs = { alc880_volume_init_verbs,
4394 alc880_lg_init_verbs },
4395 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
4396 .dac_nids = alc880_lg_dac_nids,
4397 .dig_out_nid = ALC880_DIGOUT_NID,
4398 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
4399 .channel_mode = alc880_lg_ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004400 .need_dac_fix = 1,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004401 .input_mux = &alc880_lg_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004402 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004403 .setup = alc880_lg_setup,
4404 .init_hook = alc_automute_amp,
Takashi Iwaicb53c622007-08-10 17:21:45 +02004405#ifdef CONFIG_SND_HDA_POWER_SAVE
4406 .loopbacks = alc880_lg_loopbacks,
4407#endif
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004408 },
Takashi Iwaid6815182006-03-23 16:06:23 +01004409 [ALC880_LG_LW] = {
4410 .mixers = { alc880_lg_lw_mixer },
4411 .init_verbs = { alc880_volume_init_verbs,
4412 alc880_lg_lw_init_verbs },
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02004413 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwaid6815182006-03-23 16:06:23 +01004414 .dac_nids = alc880_dac_nids,
4415 .dig_out_nid = ALC880_DIGOUT_NID,
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02004416 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
4417 .channel_mode = alc880_lg_lw_modes,
Takashi Iwaid6815182006-03-23 16:06:23 +01004418 .input_mux = &alc880_lg_lw_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004419 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004420 .setup = alc880_lg_lw_setup,
4421 .init_hook = alc_automute_amp,
Takashi Iwaid6815182006-03-23 16:06:23 +01004422 },
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004423 [ALC880_MEDION_RIM] = {
4424 .mixers = { alc880_medion_rim_mixer },
4425 .init_verbs = { alc880_volume_init_verbs,
4426 alc880_medion_rim_init_verbs,
4427 alc_gpio2_init_verbs },
4428 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4429 .dac_nids = alc880_dac_nids,
4430 .dig_out_nid = ALC880_DIGOUT_NID,
4431 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4432 .channel_mode = alc880_2_jack_modes,
4433 .input_mux = &alc880_medion_rim_capture_source,
4434 .unsol_event = alc880_medion_rim_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004435 .setup = alc880_medion_rim_setup,
4436 .init_hook = alc880_medion_rim_automute,
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004437 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004438#ifdef CONFIG_SND_DEBUG
4439 [ALC880_TEST] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004440 .mixers = { alc880_test_mixer },
4441 .init_verbs = { alc880_test_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004442 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
4443 .dac_nids = alc880_test_dac_nids,
4444 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004445 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
4446 .channel_mode = alc880_test_modes,
4447 .input_mux = &alc880_test_capture_source,
4448 },
4449#endif
4450};
4451
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004452/*
4453 * Automatic parse of I/O pins from the BIOS configuration
4454 */
4455
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004456enum {
4457 ALC_CTL_WIDGET_VOL,
4458 ALC_CTL_WIDGET_MUTE,
4459 ALC_CTL_BIND_MUTE,
4460};
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01004461static struct snd_kcontrol_new alc880_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004462 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
4463 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01004464 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004465};
4466
4467/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004468static int add_control(struct alc_spec *spec, int type, const char *name,
4469 unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004470{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01004471 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004472
Takashi Iwai603c4012008-07-30 15:01:44 +02004473 snd_array_init(&spec->kctls, sizeof(*knew), 32);
4474 knew = snd_array_new(&spec->kctls);
4475 if (!knew)
4476 return -ENOMEM;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004477 *knew = alc880_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07004478 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004479 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004480 return -ENOMEM;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01004481 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01004482 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004483 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004484 return 0;
4485}
4486
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004487static int add_control_with_pfx(struct alc_spec *spec, int type,
4488 const char *pfx, const char *dir,
4489 const char *sfx, unsigned long val)
4490{
4491 char name[32];
4492 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
4493 return add_control(spec, type, name, val);
4494}
4495
4496#define add_pb_vol_ctrl(spec, type, pfx, val) \
4497 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val)
4498#define add_pb_sw_ctrl(spec, type, pfx, val) \
4499 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val)
4500
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004501#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
4502#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
4503#define alc880_is_multi_pin(nid) ((nid) >= 0x18)
4504#define alc880_multi_pin_idx(nid) ((nid) - 0x18)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004505#define alc880_idx_to_dac(nid) ((nid) + 0x02)
4506#define alc880_dac_to_idx(nid) ((nid) - 0x02)
4507#define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
4508#define alc880_idx_to_selector(nid) ((nid) + 0x10)
4509#define ALC880_PIN_CD_NID 0x1c
4510
4511/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004512static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
4513 const struct auto_pin_cfg *cfg)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004514{
4515 hda_nid_t nid;
4516 int assigned[4];
4517 int i, j;
4518
4519 memset(assigned, 0, sizeof(assigned));
Takashi Iwaib0af0de2005-06-21 14:49:19 +02004520 spec->multiout.dac_nids = spec->private_dac_nids;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004521
4522 /* check the pins hardwired to audio widget */
4523 for (i = 0; i < cfg->line_outs; i++) {
4524 nid = cfg->line_out_pins[i];
4525 if (alc880_is_fixed_pin(nid)) {
4526 int idx = alc880_fixed_pin_idx(nid);
Libin Yang5014f192005-11-23 15:48:36 +01004527 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004528 assigned[idx] = 1;
4529 }
4530 }
4531 /* left pins can be connect to any audio widget */
4532 for (i = 0; i < cfg->line_outs; i++) {
4533 nid = cfg->line_out_pins[i];
4534 if (alc880_is_fixed_pin(nid))
4535 continue;
4536 /* search for an empty channel */
4537 for (j = 0; j < cfg->line_outs; j++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004538 if (!assigned[j]) {
4539 spec->multiout.dac_nids[i] =
4540 alc880_idx_to_dac(j);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004541 assigned[j] = 1;
4542 break;
4543 }
4544 }
4545 }
4546 spec->multiout.num_dacs = cfg->line_outs;
4547 return 0;
4548}
4549
4550/* add playback controls from the parsed DAC table */
Kailang Yangdf694da2005-12-05 19:42:22 +01004551static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
4552 const struct auto_pin_cfg *cfg)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004553{
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004554 static const char *chname[4] = {
4555 "Front", "Surround", NULL /*CLFE*/, "Side"
4556 };
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004557 hda_nid_t nid;
4558 int i, err;
4559
4560 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004561 if (!spec->multiout.dac_nids[i])
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004562 continue;
4563 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
4564 if (i == 2) {
4565 /* Center/LFE */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004566 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
4567 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004568 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
4569 HDA_OUTPUT));
4570 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004571 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004572 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
4573 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004574 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
4575 HDA_OUTPUT));
4576 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004577 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004578 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
4579 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004580 HDA_COMPOSE_AMP_VAL(nid, 1, 2,
4581 HDA_INPUT));
4582 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004583 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004584 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
4585 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004586 HDA_COMPOSE_AMP_VAL(nid, 2, 2,
4587 HDA_INPUT));
4588 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004589 return err;
4590 } else {
Takashi Iwaicb162b62009-08-25 16:05:03 +02004591 const char *pfx;
4592 if (cfg->line_outs == 1 &&
4593 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
4594 pfx = "Speaker";
4595 else
4596 pfx = chname[i];
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004597 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004598 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
4599 HDA_OUTPUT));
4600 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004601 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004602 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004603 HDA_COMPOSE_AMP_VAL(nid, 3, 2,
4604 HDA_INPUT));
4605 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004606 return err;
4607 }
4608 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004609 return 0;
4610}
4611
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004612/* add playback controls for speaker and HP outputs */
4613static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
4614 const char *pfx)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004615{
4616 hda_nid_t nid;
4617 int err;
4618
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004619 if (!pin)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004620 return 0;
4621
4622 if (alc880_is_fixed_pin(pin)) {
4623 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
Takashi Iwai82bc9552006-03-21 11:24:42 +01004624 /* specify the DAC as the extra output */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004625 if (!spec->multiout.hp_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004626 spec->multiout.hp_nid = nid;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004627 else
4628 spec->multiout.extra_out_nid[0] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004629 /* control HP volume/switch on the output mixer amp */
4630 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004631 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004632 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
4633 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004634 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004635 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004636 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
4637 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004638 return err;
4639 } else if (alc880_is_multi_pin(pin)) {
4640 /* set manual connection */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004641 /* we have only a switch on HP-out PIN */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004642 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004643 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
4644 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004645 return err;
4646 }
4647 return 0;
4648}
4649
4650/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004651static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
4652 const char *ctlname,
Kailang Yangdf694da2005-12-05 19:42:22 +01004653 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004654{
Kailang Yangdf694da2005-12-05 19:42:22 +01004655 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004656
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004657 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004658 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4659 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004660 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004661 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004662 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4663 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004664 return err;
4665 return 0;
4666}
4667
Takashi Iwai05f5f472009-08-25 13:10:18 +02004668static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004669{
Takashi Iwai05f5f472009-08-25 13:10:18 +02004670 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
4671 return (pincap & AC_PINCAP_IN) != 0;
4672}
4673
4674/* create playback/capture controls for input pins */
4675static int alc_auto_create_input_ctls(struct hda_codec *codec,
4676 const struct auto_pin_cfg *cfg,
4677 hda_nid_t mixer,
4678 hda_nid_t cap1, hda_nid_t cap2)
4679{
4680 struct alc_spec *spec = codec->spec;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02004681 struct hda_input_mux *imux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01004682 int i, err, idx;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004683
4684 for (i = 0; i < AUTO_PIN_LAST; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02004685 hda_nid_t pin;
4686
4687 pin = cfg->input_pins[i];
4688 if (!alc_is_input_pin(codec, pin))
4689 continue;
4690
4691 if (mixer) {
4692 idx = get_connection_index(codec, mixer, pin);
4693 if (idx >= 0) {
4694 err = new_analog_input(spec, pin,
4695 auto_pin_cfg_labels[i],
4696 idx, mixer);
4697 if (err < 0)
4698 return err;
4699 }
4700 }
4701
4702 if (!cap1)
4703 continue;
4704 idx = get_connection_index(codec, cap1, pin);
4705 if (idx < 0 && cap2)
4706 idx = get_connection_index(codec, cap2, pin);
4707 if (idx >= 0) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004708 imux->items[imux->num_items].label =
4709 auto_pin_cfg_labels[i];
Takashi Iwai05f5f472009-08-25 13:10:18 +02004710 imux->items[imux->num_items].index = idx;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004711 imux->num_items++;
4712 }
4713 }
4714 return 0;
4715}
4716
Takashi Iwai05f5f472009-08-25 13:10:18 +02004717static int alc880_auto_create_input_ctls(struct hda_codec *codec,
4718 const struct auto_pin_cfg *cfg)
4719{
4720 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x08, 0x09);
4721}
4722
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004723static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
4724 unsigned int pin_type)
4725{
4726 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4727 pin_type);
4728 /* unmute pin */
Takashi Iwaid260cdf2008-02-13 17:19:35 +01004729 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4730 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004731}
4732
Kailang Yangdf694da2005-12-05 19:42:22 +01004733static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
4734 hda_nid_t nid, int pin_type,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004735 int dac_idx)
4736{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004737 alc_set_pin_output(codec, nid, pin_type);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004738 /* need the manual connection? */
4739 if (alc880_is_multi_pin(nid)) {
4740 struct alc_spec *spec = codec->spec;
4741 int idx = alc880_multi_pin_idx(nid);
4742 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
4743 AC_VERB_SET_CONNECT_SEL,
4744 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
4745 }
4746}
4747
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02004748static int get_pin_type(int line_out_type)
4749{
4750 if (line_out_type == AUTO_PIN_HP_OUT)
4751 return PIN_HP;
4752 else
4753 return PIN_OUT;
4754}
4755
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004756static void alc880_auto_init_multi_out(struct hda_codec *codec)
4757{
4758 struct alc_spec *spec = codec->spec;
4759 int i;
Kailang Yangea1fb292008-08-26 12:58:38 +02004760
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004761 for (i = 0; i < spec->autocfg.line_outs; i++) {
4762 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02004763 int pin_type = get_pin_type(spec->autocfg.line_out_type);
4764 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004765 }
4766}
4767
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004768static void alc880_auto_init_extra_out(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004769{
4770 struct alc_spec *spec = codec->spec;
4771 hda_nid_t pin;
4772
Takashi Iwai82bc9552006-03-21 11:24:42 +01004773 pin = spec->autocfg.speaker_pins[0];
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004774 if (pin) /* connect to front */
4775 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02004776 pin = spec->autocfg.hp_pins[0];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004777 if (pin) /* connect to front */
4778 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
4779}
4780
4781static void alc880_auto_init_analog_input(struct hda_codec *codec)
4782{
4783 struct alc_spec *spec = codec->spec;
4784 int i;
4785
4786 for (i = 0; i < AUTO_PIN_LAST; i++) {
4787 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai05f5f472009-08-25 13:10:18 +02004788 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +01004789 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +01004790 if (nid != ALC880_PIN_CD_NID &&
4791 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004792 snd_hda_codec_write(codec, nid, 0,
4793 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004794 AMP_OUT_MUTE);
4795 }
4796 }
4797}
4798
4799/* parse the BIOS configuration and set up the alc_spec */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004800/* return 1 if successful, 0 if the proper config is not found,
4801 * or a negative error code
4802 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004803static int alc880_parse_auto_config(struct hda_codec *codec)
4804{
4805 struct alc_spec *spec = codec->spec;
Takashi Iwai6a05ac42009-02-13 11:19:09 +01004806 int i, err;
Kailang Yangdf694da2005-12-05 19:42:22 +01004807 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004808
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004809 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4810 alc880_ignore);
4811 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004812 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004813 if (!spec->autocfg.line_outs)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004814 return 0; /* can't find valid BIOS pin config */
Kailang Yangdf694da2005-12-05 19:42:22 +01004815
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004816 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
4817 if (err < 0)
4818 return err;
4819 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
4820 if (err < 0)
4821 return err;
4822 err = alc880_auto_create_extra_out(spec,
4823 spec->autocfg.speaker_pins[0],
4824 "Speaker");
4825 if (err < 0)
4826 return err;
4827 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
4828 "Headphone");
4829 if (err < 0)
4830 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +02004831 err = alc880_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004832 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004833 return err;
4834
4835 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4836
Takashi Iwai6a05ac42009-02-13 11:19:09 +01004837 /* check multiple SPDIF-out (for recent codecs) */
4838 for (i = 0; i < spec->autocfg.dig_outs; i++) {
4839 hda_nid_t dig_nid;
4840 err = snd_hda_get_connections(codec,
4841 spec->autocfg.dig_out_pins[i],
4842 &dig_nid, 1);
4843 if (err < 0)
4844 continue;
4845 if (!i)
4846 spec->multiout.dig_out_nid = dig_nid;
4847 else {
4848 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
Roel Kluin71121d9f2009-11-10 20:11:55 +01004849 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
Takashi Iwai6a05ac42009-02-13 11:19:09 +01004850 break;
Roel Kluin71121d9f2009-11-10 20:11:55 +01004851 spec->slave_dig_outs[i - 1] = dig_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +01004852 }
4853 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004854 if (spec->autocfg.dig_in_pin)
4855 spec->dig_in_nid = ALC880_DIGIN_NID;
4856
Takashi Iwai603c4012008-07-30 15:01:44 +02004857 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +01004858 add_mixer(spec, spec->kctls.list);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004859
Takashi Iwaid88897e2008-10-31 15:01:37 +01004860 add_verb(spec, alc880_volume_init_verbs);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004861
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02004862 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02004863 spec->input_mux = &spec->private_imux[0];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004864
Kailang Yang6227cdc2010-02-25 08:36:52 +01004865 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02004866
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004867 return 1;
4868}
4869
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004870/* additional initialization for auto-configuration model */
4871static void alc880_auto_init(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004872{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004873 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004874 alc880_auto_init_multi_out(codec);
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004875 alc880_auto_init_extra_out(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004876 alc880_auto_init_analog_input(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004877 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +02004878 alc_inithook(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004879}
4880
Takashi Iwaib59bdf32009-08-11 09:47:30 +02004881/* check the ADC/MUX contains all input pins; some ADC/MUX contains only
4882 * one of two digital mic pins, e.g. on ALC272
4883 */
4884static void fixup_automic_adc(struct hda_codec *codec)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01004885{
Takashi Iwaib59bdf32009-08-11 09:47:30 +02004886 struct alc_spec *spec = codec->spec;
4887 int i;
4888
4889 for (i = 0; i < spec->num_adc_nids; i++) {
4890 hda_nid_t cap = spec->capsrc_nids ?
4891 spec->capsrc_nids[i] : spec->adc_nids[i];
4892 int iidx, eidx;
4893
4894 iidx = get_connection_index(codec, cap, spec->int_mic.pin);
4895 if (iidx < 0)
4896 continue;
4897 eidx = get_connection_index(codec, cap, spec->ext_mic.pin);
4898 if (eidx < 0)
4899 continue;
4900 spec->int_mic.mux_idx = iidx;
4901 spec->ext_mic.mux_idx = eidx;
4902 if (spec->capsrc_nids)
4903 spec->capsrc_nids += i;
4904 spec->adc_nids += i;
4905 spec->num_adc_nids = 1;
4906 return;
4907 }
4908 snd_printd(KERN_INFO "hda_codec: %s: "
4909 "No ADC/MUX containing both 0x%x and 0x%x pins\n",
4910 codec->chip_name, spec->int_mic.pin, spec->ext_mic.pin);
4911 spec->auto_mic = 0; /* disable auto-mic to be sure */
4912}
4913
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01004914/* choose the ADC/MUX containing the input pin and initialize the setup */
4915static void fixup_single_adc(struct hda_codec *codec)
4916{
4917 struct alc_spec *spec = codec->spec;
4918 hda_nid_t pin;
4919 int i;
4920
4921 /* search for the input pin; there must be only one */
4922 for (i = 0; i < AUTO_PIN_LAST; i++) {
4923 if (spec->autocfg.input_pins[i]) {
4924 pin = spec->autocfg.input_pins[i];
4925 break;
4926 }
4927 }
4928 if (!pin)
4929 return;
4930
4931 /* set the default connection to that pin */
4932 for (i = 0; i < spec->num_adc_nids; i++) {
4933 hda_nid_t cap = spec->capsrc_nids ?
4934 spec->capsrc_nids[i] : spec->adc_nids[i];
4935 int idx;
4936
4937 idx = get_connection_index(codec, cap, pin);
4938 if (idx < 0)
4939 continue;
4940 /* use only this ADC */
4941 if (spec->capsrc_nids)
4942 spec->capsrc_nids += i;
4943 spec->adc_nids += i;
4944 spec->num_adc_nids = 1;
4945 /* select or unmute this route */
4946 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
4947 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
4948 HDA_AMP_MUTE, 0);
4949 } else {
4950 snd_hda_codec_write_cache(codec, cap, 0,
4951 AC_VERB_SET_CONNECT_SEL, idx);
4952 }
4953 return;
4954 }
4955}
4956
Takashi Iwaib59bdf32009-08-11 09:47:30 +02004957static void set_capture_mixer(struct hda_codec *codec)
4958{
4959 struct alc_spec *spec = codec->spec;
Takashi Iwaia23b6882009-03-23 15:21:36 +01004960 static struct snd_kcontrol_new *caps[2][3] = {
4961 { alc_capture_mixer_nosrc1,
4962 alc_capture_mixer_nosrc2,
4963 alc_capture_mixer_nosrc3 },
4964 { alc_capture_mixer1,
4965 alc_capture_mixer2,
4966 alc_capture_mixer3 },
Takashi Iwaif9e336f2008-10-31 16:37:07 +01004967 };
Takashi Iwaia23b6882009-03-23 15:21:36 +01004968 if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01004969 int mux = 0;
4970 if (spec->auto_mic)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02004971 fixup_automic_adc(codec);
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01004972 else if (spec->input_mux) {
4973 if (spec->input_mux->num_items > 1)
4974 mux = 1;
4975 else if (spec->input_mux->num_items == 1)
4976 fixup_single_adc(codec);
4977 }
Takashi Iwaia23b6882009-03-23 15:21:36 +01004978 spec->cap_mixer = caps[mux][spec->num_adc_nids - 1];
4979 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01004980}
4981
Takashi Iwai67d634c2009-11-16 15:35:59 +01004982#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01004983#define set_beep_amp(spec, nid, idx, dir) \
4984 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
Takashi Iwai67d634c2009-11-16 15:35:59 +01004985#else
4986#define set_beep_amp(spec, nid, idx, dir) /* NOP */
4987#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01004988
4989/*
4990 * OK, here we have finally the patch for ALC880
4991 */
4992
Linus Torvalds1da177e2005-04-16 15:20:36 -07004993static int patch_alc880(struct hda_codec *codec)
4994{
4995 struct alc_spec *spec;
4996 int board_config;
Kailang Yangdf694da2005-12-05 19:42:22 +01004997 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998
Takashi Iwaie560d8d2005-09-09 14:21:46 +02004999 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000 if (spec == NULL)
5001 return -ENOMEM;
5002
5003 codec->spec = spec;
5004
Takashi Iwaif5fcc132006-11-24 17:07:44 +01005005 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
5006 alc880_models,
5007 alc880_cfg_tbl);
5008 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005009 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5010 codec->chip_name);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005011 board_config = ALC880_AUTO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012 }
5013
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005014 if (board_config == ALC880_AUTO) {
5015 /* automatic parse from the BIOS config */
5016 err = alc880_parse_auto_config(codec);
5017 if (err < 0) {
5018 alc_free(codec);
5019 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005020 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02005021 printk(KERN_INFO
5022 "hda_codec: Cannot set up configuration "
5023 "from BIOS. Using 3-stack mode...\n");
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005024 board_config = ALC880_3ST;
5025 }
5026 }
5027
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09005028 err = snd_hda_attach_beep_device(codec, 0x1);
5029 if (err < 0) {
5030 alc_free(codec);
5031 return err;
5032 }
5033
Kailang Yangdf694da2005-12-05 19:42:22 +01005034 if (board_config != ALC880_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005035 setup_preset(codec, &alc880_presets[board_config]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036
Linus Torvalds1da177e2005-04-16 15:20:36 -07005037 spec->stream_analog_playback = &alc880_pcm_analog_playback;
5038 spec->stream_analog_capture = &alc880_pcm_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +01005039 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
Linus Torvalds1da177e2005-04-16 15:20:36 -07005041 spec->stream_digital_playback = &alc880_pcm_digital_playback;
5042 spec->stream_digital_capture = &alc880_pcm_digital_capture;
5043
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005044 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005045 /* check whether NID 0x07 is valid */
Takashi Iwai54d17402005-11-21 16:33:22 +01005046 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005047 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +02005048 wcap = get_wcaps_type(wcap);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005049 if (wcap != AC_WID_AUD_IN) {
5050 spec->adc_nids = alc880_adc_nids_alt;
5051 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005052 } else {
5053 spec->adc_nids = alc880_adc_nids;
5054 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005055 }
5056 }
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005057 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01005058 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059
Takashi Iwai2134ea42008-01-10 16:53:55 +01005060 spec->vmaster_nid = 0x0c;
5061
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062 codec->patch_ops = alc_patch_ops;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005063 if (board_config == ALC880_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01005064 spec->init_hook = alc880_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +02005065#ifdef CONFIG_SND_HDA_POWER_SAVE
5066 if (!spec->loopback.amplist)
5067 spec->loopback.amplist = alc880_loopbacks;
5068#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069
5070 return 0;
5071}
5072
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005073
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074/*
5075 * ALC260 support
5076 */
5077
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005078static hda_nid_t alc260_dac_nids[1] = {
5079 /* front */
5080 0x02,
5081};
5082
5083static hda_nid_t alc260_adc_nids[1] = {
5084 /* ADC0 */
5085 0x04,
5086};
5087
Kailang Yangdf694da2005-12-05 19:42:22 +01005088static hda_nid_t alc260_adc_nids_alt[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005089 /* ADC1 */
5090 0x05,
5091};
5092
Jonathan Woithed57fdac2006-02-28 11:38:35 +01005093/* NIDs used when simultaneous access to both ADCs makes sense. Note that
5094 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
5095 */
5096static hda_nid_t alc260_dual_adc_nids[2] = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005097 /* ADC0, ADC1 */
5098 0x04, 0x05
5099};
5100
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005101#define ALC260_DIGOUT_NID 0x03
5102#define ALC260_DIGIN_NID 0x06
5103
5104static struct hda_input_mux alc260_capture_source = {
5105 .num_items = 4,
5106 .items = {
5107 { "Mic", 0x0 },
5108 { "Front Mic", 0x1 },
5109 { "Line", 0x2 },
5110 { "CD", 0x4 },
5111 },
5112};
5113
Jonathan Woithe17e7aec2006-02-28 11:35:18 +01005114/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005115 * headphone jack and the internal CD lines since these are the only pins at
5116 * which audio can appear. For flexibility, also allow the option of
5117 * recording the mixer output on the second ADC (ADC0 doesn't have a
5118 * connection to the mixer output).
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005119 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005120static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
5121 {
5122 .num_items = 3,
5123 .items = {
5124 { "Mic/Line", 0x0 },
5125 { "CD", 0x4 },
5126 { "Headphone", 0x2 },
5127 },
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005128 },
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005129 {
5130 .num_items = 4,
5131 .items = {
5132 { "Mic/Line", 0x0 },
5133 { "CD", 0x4 },
5134 { "Headphone", 0x2 },
5135 { "Mixer", 0x5 },
5136 },
5137 },
5138
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005139};
5140
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005141/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
5142 * the Fujitsu S702x, but jacks are marked differently.
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005143 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005144static struct hda_input_mux alc260_acer_capture_sources[2] = {
5145 {
5146 .num_items = 4,
5147 .items = {
5148 { "Mic", 0x0 },
5149 { "Line", 0x2 },
5150 { "CD", 0x4 },
5151 { "Headphone", 0x5 },
5152 },
5153 },
5154 {
5155 .num_items = 5,
5156 .items = {
5157 { "Mic", 0x0 },
5158 { "Line", 0x2 },
5159 { "CD", 0x4 },
5160 { "Headphone", 0x6 },
5161 { "Mixer", 0x5 },
5162 },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005163 },
5164};
Michael Schwingencc959482009-02-22 18:58:45 +01005165
5166/* Maxdata Favorit 100XS */
5167static struct hda_input_mux alc260_favorit100_capture_sources[2] = {
5168 {
5169 .num_items = 2,
5170 .items = {
5171 { "Line/Mic", 0x0 },
5172 { "CD", 0x4 },
5173 },
5174 },
5175 {
5176 .num_items = 3,
5177 .items = {
5178 { "Line/Mic", 0x0 },
5179 { "CD", 0x4 },
5180 { "Mixer", 0x5 },
5181 },
5182 },
5183};
5184
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185/*
5186 * This is just place-holder, so there's something for alc_build_pcms to look
5187 * at when it calculates the maximum number of channels. ALC260 has no mixer
5188 * element which allows changing the channel mode, so the verb list is
5189 * never used.
5190 */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01005191static struct hda_channel_mode alc260_modes[1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192 { 2, NULL },
5193};
5194
Kailang Yangdf694da2005-12-05 19:42:22 +01005195
5196/* Mixer combinations
5197 *
5198 * basic: base_output + input + pc_beep + capture
5199 * HP: base_output + input + capture_alt
5200 * HP_3013: hp_3013 + input + capture
5201 * fujitsu: fujitsu + capture
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005202 * acer: acer + capture
Kailang Yangdf694da2005-12-05 19:42:22 +01005203 */
5204
5205static struct snd_kcontrol_new alc260_base_output_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02005206 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01005207 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01005208 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5209 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
5210 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
5211 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
5212 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005213};
Kailang Yangdf694da2005-12-05 19:42:22 +01005214
5215static struct snd_kcontrol_new alc260_input_mixer[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5217 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5218 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5219 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5220 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5221 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5222 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
5223 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224 { } /* end */
5225};
5226
Takashi Iwaibec15c32008-01-28 18:16:30 +01005227/* update HP, line and mono out pins according to the master switch */
5228static void alc260_hp_master_update(struct hda_codec *codec,
5229 hda_nid_t hp, hda_nid_t line,
5230 hda_nid_t mono)
5231{
5232 struct alc_spec *spec = codec->spec;
5233 unsigned int val = spec->master_sw ? PIN_HP : 0;
5234 /* change HP and line-out pins */
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005235 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005236 val);
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005237 snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005238 val);
5239 /* mono (speaker) depending on the HP jack sense */
5240 val = (val && !spec->jack_present) ? PIN_OUT : 0;
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005241 snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005242 val);
5243}
5244
5245static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
5246 struct snd_ctl_elem_value *ucontrol)
5247{
5248 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5249 struct alc_spec *spec = codec->spec;
5250 *ucontrol->value.integer.value = spec->master_sw;
5251 return 0;
5252}
5253
5254static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
5255 struct snd_ctl_elem_value *ucontrol)
5256{
5257 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5258 struct alc_spec *spec = codec->spec;
5259 int val = !!*ucontrol->value.integer.value;
5260 hda_nid_t hp, line, mono;
5261
5262 if (val == spec->master_sw)
5263 return 0;
5264 spec->master_sw = val;
5265 hp = (kcontrol->private_value >> 16) & 0xff;
5266 line = (kcontrol->private_value >> 8) & 0xff;
5267 mono = kcontrol->private_value & 0xff;
5268 alc260_hp_master_update(codec, hp, line, mono);
5269 return 1;
5270}
5271
5272static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
5273 {
5274 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5275 .name = "Master Playback Switch",
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01005276 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005277 .info = snd_ctl_boolean_mono_info,
5278 .get = alc260_hp_master_sw_get,
5279 .put = alc260_hp_master_sw_put,
5280 .private_value = (0x0f << 16) | (0x10 << 8) | 0x11
5281 },
5282 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5283 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
5284 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5285 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
5286 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
5287 HDA_OUTPUT),
5288 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
5289 { } /* end */
5290};
5291
5292static struct hda_verb alc260_hp_unsol_verbs[] = {
5293 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5294 {},
5295};
5296
5297static void alc260_hp_automute(struct hda_codec *codec)
5298{
5299 struct alc_spec *spec = codec->spec;
Takashi Iwaibec15c32008-01-28 18:16:30 +01005300
Wu Fengguang864f92b2009-11-18 12:38:02 +08005301 spec->jack_present = snd_hda_jack_detect(codec, 0x10);
Takashi Iwaibec15c32008-01-28 18:16:30 +01005302 alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
5303}
5304
5305static void alc260_hp_unsol_event(struct hda_codec *codec, unsigned int res)
5306{
5307 if ((res >> 26) == ALC880_HP_EVENT)
5308 alc260_hp_automute(codec);
5309}
5310
Kailang Yangdf694da2005-12-05 19:42:22 +01005311static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
Takashi Iwaibec15c32008-01-28 18:16:30 +01005312 {
5313 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5314 .name = "Master Playback Switch",
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01005315 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005316 .info = snd_ctl_boolean_mono_info,
5317 .get = alc260_hp_master_sw_get,
5318 .put = alc260_hp_master_sw_put,
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005319 .private_value = (0x15 << 16) | (0x10 << 8) | 0x11
Takashi Iwaibec15c32008-01-28 18:16:30 +01005320 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005321 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5322 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
5323 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
5324 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
5325 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5326 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +01005327 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
5328 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02005329 { } /* end */
5330};
5331
Kailang Yang3f878302008-08-26 13:02:23 +02005332static struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
5333 .ops = &snd_hda_bind_vol,
5334 .values = {
5335 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
5336 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
5337 HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT),
5338 0
5339 },
5340};
5341
5342static struct hda_bind_ctls alc260_dc7600_bind_switch = {
5343 .ops = &snd_hda_bind_sw,
5344 .values = {
5345 HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
5346 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
5347 0
5348 },
5349};
5350
5351static struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
5352 HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
5353 HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
5354 HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
5355 HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
5356 { } /* end */
5357};
5358
Takashi Iwaibec15c32008-01-28 18:16:30 +01005359static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
5360 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5361 {},
5362};
5363
5364static void alc260_hp_3013_automute(struct hda_codec *codec)
5365{
5366 struct alc_spec *spec = codec->spec;
Takashi Iwaibec15c32008-01-28 18:16:30 +01005367
Wu Fengguang864f92b2009-11-18 12:38:02 +08005368 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005369 alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
Takashi Iwaibec15c32008-01-28 18:16:30 +01005370}
5371
5372static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
5373 unsigned int res)
5374{
5375 if ((res >> 26) == ALC880_HP_EVENT)
5376 alc260_hp_3013_automute(codec);
5377}
5378
Kailang Yang3f878302008-08-26 13:02:23 +02005379static void alc260_hp_3012_automute(struct hda_codec *codec)
5380{
Wu Fengguang864f92b2009-11-18 12:38:02 +08005381 unsigned int bits = snd_hda_jack_detect(codec, 0x10) ? 0 : PIN_OUT;
Kailang Yang3f878302008-08-26 13:02:23 +02005382
Kailang Yang3f878302008-08-26 13:02:23 +02005383 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5384 bits);
5385 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5386 bits);
5387 snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5388 bits);
5389}
5390
5391static void alc260_hp_3012_unsol_event(struct hda_codec *codec,
5392 unsigned int res)
5393{
5394 if ((res >> 26) == ALC880_HP_EVENT)
5395 alc260_hp_3012_automute(codec);
5396}
5397
5398/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005399 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
5400 */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01005401static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005402 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01005403 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005404 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005405 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5406 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5407 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
5408 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005409 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005410 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5411 HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01005412 { } /* end */
5413};
5414
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005415/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
5416 * versions of the ALC260 don't act on requests to enable mic bias from NID
5417 * 0x0f (used to drive the headphone jack in these laptops). The ALC260
5418 * datasheet doesn't mention this restriction. At this stage it's not clear
5419 * whether this behaviour is intentional or is a hardware bug in chip
5420 * revisions available in early 2006. Therefore for now allow the
5421 * "Headphone Jack Mode" control to span all choices, but if it turns out
5422 * that the lack of mic bias for this NID is intentional we could change the
5423 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
5424 *
5425 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
5426 * don't appear to make the mic bias available from the "line" jack, even
5427 * though the NID used for this jack (0x14) can supply it. The theory is
5428 * that perhaps Acer have included blocking capacitors between the ALC260
5429 * and the output jack. If this turns out to be the case for all such
5430 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
5431 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
Jonathan Woithebd869482006-11-28 11:35:52 +01005432 *
5433 * The C20x Tablet series have a mono internal speaker which is controlled
5434 * via the chip's Mono sum widget and pin complex, so include the necessary
5435 * controls for such models. On models without a "mono speaker" the control
5436 * won't do anything.
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005437 */
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005438static struct snd_kcontrol_new alc260_acer_mixer[] = {
5439 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5440 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005441 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005442 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
Jonathan Woithebd869482006-11-28 11:35:52 +01005443 HDA_OUTPUT),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005444 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
Jonathan Woithebd869482006-11-28 11:35:52 +01005445 HDA_INPUT),
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005446 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5447 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5448 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5449 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5450 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5451 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5452 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5453 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005454 { } /* end */
5455};
5456
Michael Schwingencc959482009-02-22 18:58:45 +01005457/* Maxdata Favorit 100XS: one output and one input (0x12) jack
5458 */
5459static struct snd_kcontrol_new alc260_favorit100_mixer[] = {
5460 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5461 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
5462 ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
5463 HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5464 HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5465 ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5466 { } /* end */
5467};
5468
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005469/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
5470 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
5471 */
5472static struct snd_kcontrol_new alc260_will_mixer[] = {
5473 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5474 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
5475 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5476 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5477 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5478 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5479 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5480 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
5481 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5482 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005483 { } /* end */
5484};
5485
5486/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
5487 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
5488 */
5489static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
5490 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5491 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
5492 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5493 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5494 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5495 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
5496 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
5497 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5498 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5499 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
5500 { } /* end */
5501};
5502
Kailang Yangdf694da2005-12-05 19:42:22 +01005503/*
5504 * initialization verbs
5505 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005506static struct hda_verb alc260_init_verbs[] = {
5507 /* Line In pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02005508 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509 /* CD pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02005510 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511 /* Mic1 (rear panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02005512 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005513 /* Mic2 (front panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02005514 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 /* LINE-2 is used for line-out in rear */
Takashi Iwai05acb862005-06-10 19:50:25 +02005516 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005517 /* select line-out */
Jonathan Woithefd56f2d2006-01-24 10:35:46 +01005518 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519 /* LINE-OUT pin */
Takashi Iwai05acb862005-06-10 19:50:25 +02005520 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521 /* enable HP */
Takashi Iwai05acb862005-06-10 19:50:25 +02005522 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005523 /* enable Mono */
Takashi Iwai05acb862005-06-10 19:50:25 +02005524 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5525 /* mute capture amp left and right */
Takashi Iwai16ded522005-06-10 19:58:24 +02005526 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005527 /* set connection select to line in (default select for this ADC) */
5528 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai16ded522005-06-10 19:58:24 +02005529 /* mute capture amp left and right */
5530 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5531 /* set connection select to line in (default select for this ADC) */
5532 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai05acb862005-06-10 19:50:25 +02005533 /* set vol=0 Line-Out mixer amp left and right */
5534 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5535 /* unmute pin widget amp left and right (no gain on this amp) */
5536 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5537 /* set vol=0 HP mixer amp left and right */
5538 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5539 /* unmute pin widget amp left and right (no gain on this amp) */
5540 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5541 /* set vol=0 Mono mixer amp left and right */
5542 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5543 /* unmute pin widget amp left and right (no gain on this amp) */
5544 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5545 /* unmute LINE-2 out pin */
5546 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005547 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
5548 * Line In 2 = 0x03
5549 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02005550 /* mute analog inputs */
5551 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5552 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5553 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5554 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5555 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
Takashi Iwai05acb862005-06-10 19:50:25 +02005557 /* mute Front out path */
5558 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5559 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5560 /* mute Headphone out path */
5561 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5562 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5563 /* mute Mono out path */
5564 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5565 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566 { }
5567};
5568
Takashi Iwai474167d2006-05-17 17:17:43 +02005569#if 0 /* should be identical with alc260_init_verbs? */
Kailang Yangdf694da2005-12-05 19:42:22 +01005570static struct hda_verb alc260_hp_init_verbs[] = {
5571 /* Headphone and output */
5572 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
5573 /* mono output */
5574 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5575 /* Mic1 (rear panel) pin widget for input and vref at 80% */
5576 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5577 /* Mic2 (front panel) pin widget for input and vref at 80% */
5578 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5579 /* Line In pin widget for input */
5580 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5581 /* Line-2 pin widget for output */
5582 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5583 /* CD pin widget for input */
5584 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5585 /* unmute amp left and right */
5586 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
5587 /* set connection select to line in (default select for this ADC) */
5588 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
5589 /* unmute Line-Out mixer amp left and right (volume = 0) */
5590 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5591 /* mute pin widget amp left and right (no gain on this amp) */
5592 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5593 /* unmute HP mixer amp left and right (volume = 0) */
5594 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5595 /* mute pin widget amp left and right (no gain on this amp) */
5596 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005597 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
5598 * Line In 2 = 0x03
5599 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02005600 /* mute analog inputs */
5601 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5602 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5603 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5604 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5605 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01005606 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
5607 /* Unmute Front out path */
5608 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5609 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5610 /* Unmute Headphone out path */
5611 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5612 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5613 /* Unmute Mono out path */
5614 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5615 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5616 { }
5617};
Takashi Iwai474167d2006-05-17 17:17:43 +02005618#endif
Kailang Yangdf694da2005-12-05 19:42:22 +01005619
5620static struct hda_verb alc260_hp_3013_init_verbs[] = {
5621 /* Line out and output */
5622 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5623 /* mono output */
5624 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5625 /* Mic1 (rear panel) pin widget for input and vref at 80% */
5626 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5627 /* Mic2 (front panel) pin widget for input and vref at 80% */
5628 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5629 /* Line In pin widget for input */
5630 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5631 /* Headphone pin widget for output */
5632 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
5633 /* CD pin widget for input */
5634 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5635 /* unmute amp left and right */
5636 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
5637 /* set connection select to line in (default select for this ADC) */
5638 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
5639 /* unmute Line-Out mixer amp left and right (volume = 0) */
5640 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5641 /* mute pin widget amp left and right (no gain on this amp) */
5642 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5643 /* unmute HP mixer amp left and right (volume = 0) */
5644 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5645 /* mute pin widget amp left and right (no gain on this amp) */
5646 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005647 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
5648 * Line In 2 = 0x03
5649 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02005650 /* mute analog inputs */
5651 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5652 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5653 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5654 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5655 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01005656 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
5657 /* Unmute Front out path */
5658 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5659 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5660 /* Unmute Headphone out path */
5661 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5662 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5663 /* Unmute Mono out path */
5664 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5665 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5666 { }
5667};
5668
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005669/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005670 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
5671 * audio = 0x16, internal speaker = 0x10.
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005672 */
5673static struct hda_verb alc260_fujitsu_init_verbs[] = {
5674 /* Disable all GPIOs */
5675 {0x01, AC_VERB_SET_GPIO_MASK, 0},
5676 /* Internal speaker is connected to headphone pin */
5677 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5678 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
5679 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Jonathan Woithef7ace402006-02-28 11:46:14 +01005680 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
5681 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5682 /* Ensure all other unused pins are disabled and muted. */
5683 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5684 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005685 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
Jonathan Woithef7ace402006-02-28 11:46:14 +01005686 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005687 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
Jonathan Woithef7ace402006-02-28 11:46:14 +01005688 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5689 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5690 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005691
Jonathan Woithef7ace402006-02-28 11:46:14 +01005692 /* Disable digital (SPDIF) pins */
5693 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
5694 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005695
Kailang Yangea1fb292008-08-26 12:58:38 +02005696 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
Jonathan Woithef7ace402006-02-28 11:46:14 +01005697 * when acting as an output.
5698 */
5699 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
5700
5701 /* Start with output sum widgets muted and their output gains at min */
Takashi Iwai8b33a5a2006-02-09 11:57:01 +01005702 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5703 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5704 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5705 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5706 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5707 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5708 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5709 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5710 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005711
Jonathan Woithef7ace402006-02-28 11:46:14 +01005712 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
5713 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5714 /* Unmute Line1 pin widget output buffer since it starts as an output.
5715 * If the pin mode is changed by the user the pin mode control will
5716 * take care of enabling the pin's input/output buffers as needed.
5717 * Therefore there's no need to enable the input buffer at this
5718 * stage.
Jonathan Woithecdcd9262006-02-28 11:36:42 +01005719 */
Jonathan Woithef7ace402006-02-28 11:46:14 +01005720 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +02005721 /* Unmute input buffer of pin widget used for Line-in (no equiv
Jonathan Woithecdcd9262006-02-28 11:36:42 +01005722 * mixer ctrl)
5723 */
Jonathan Woithef7ace402006-02-28 11:46:14 +01005724 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005725
Jonathan Woithef7ace402006-02-28 11:46:14 +01005726 /* Mute capture amp left and right */
5727 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +02005728 /* Set ADC connection select to match default mixer setting - line
Jonathan Woithef7ace402006-02-28 11:46:14 +01005729 * in (on mic1 pin)
5730 */
5731 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005732
Jonathan Woithef7ace402006-02-28 11:46:14 +01005733 /* Do the same for the second ADC: mute capture input amp and
5734 * set ADC connection to line in (on mic1 pin)
5735 */
5736 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5737 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005738
Jonathan Woithef7ace402006-02-28 11:46:14 +01005739 /* Mute all inputs to mixer widget (even unconnected ones) */
5740 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
5741 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
5742 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
5743 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
5744 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
5745 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
5746 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
5747 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
Takashi Iwai4a471b72005-12-07 13:56:29 +01005748
5749 { }
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005750};
5751
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005752/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
5753 * similar laptops (adapted from Fujitsu init verbs).
5754 */
5755static struct hda_verb alc260_acer_init_verbs[] = {
5756 /* On TravelMate laptops, GPIO 0 enables the internal speaker and
5757 * the headphone jack. Turn this on and rely on the standard mute
5758 * methods whenever the user wants to turn these outputs off.
5759 */
5760 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
5761 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5762 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5763 /* Internal speaker/Headphone jack is connected to Line-out pin */
5764 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5765 /* Internal microphone/Mic jack is connected to Mic1 pin */
5766 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
5767 /* Line In jack is connected to Line1 pin */
5768 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Jonathan Woithebd869482006-11-28 11:35:52 +01005769 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
5770 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005771 /* Ensure all other unused pins are disabled and muted. */
5772 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5773 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005774 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5775 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5776 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5777 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5778 /* Disable digital (SPDIF) pins */
5779 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
5780 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
5781
Kailang Yangea1fb292008-08-26 12:58:38 +02005782 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005783 * bus when acting as outputs.
5784 */
5785 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
5786 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
5787
5788 /* Start with output sum widgets muted and their output gains at min */
5789 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5790 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5791 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5792 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5793 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5794 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5795 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5796 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5797 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5798
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005799 /* Unmute Line-out pin widget amp left and right
5800 * (no equiv mixer ctrl)
5801 */
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005802 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Jonathan Woithebd869482006-11-28 11:35:52 +01005803 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
5804 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005805 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
5806 * inputs. If the pin mode is changed by the user the pin mode control
5807 * will take care of enabling the pin's input/output buffers as needed.
5808 * Therefore there's no need to enable the input buffer at this
5809 * stage.
5810 */
5811 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5812 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5813
5814 /* Mute capture amp left and right */
5815 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5816 /* Set ADC connection select to match default mixer setting - mic
5817 * (on mic1 pin)
5818 */
5819 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
5820
5821 /* Do similar with the second ADC: mute capture input amp and
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005822 * set ADC connection to mic to match ALSA's default state.
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005823 */
5824 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005825 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005826
5827 /* Mute all inputs to mixer widget (even unconnected ones) */
5828 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
5829 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
5830 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
5831 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
5832 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
5833 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
5834 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
5835 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
5836
5837 { }
5838};
5839
Michael Schwingencc959482009-02-22 18:58:45 +01005840/* Initialisation sequence for Maxdata Favorit 100XS
5841 * (adapted from Acer init verbs).
5842 */
5843static struct hda_verb alc260_favorit100_init_verbs[] = {
5844 /* GPIO 0 enables the output jack.
5845 * Turn this on and rely on the standard mute
5846 * methods whenever the user wants to turn these outputs off.
5847 */
5848 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
5849 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5850 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5851 /* Line/Mic input jack is connected to Mic1 pin */
5852 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
5853 /* Ensure all other unused pins are disabled and muted. */
5854 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5855 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5856 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5857 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5858 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5859 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5860 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5861 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5862 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
5863 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5864 /* Disable digital (SPDIF) pins */
5865 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
5866 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
5867
5868 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
5869 * bus when acting as outputs.
5870 */
5871 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
5872 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
5873
5874 /* Start with output sum widgets muted and their output gains at min */
5875 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5876 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5877 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5878 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5879 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5880 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5881 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5882 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5883 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5884
5885 /* Unmute Line-out pin widget amp left and right
5886 * (no equiv mixer ctrl)
5887 */
5888 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5889 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
5890 * inputs. If the pin mode is changed by the user the pin mode control
5891 * will take care of enabling the pin's input/output buffers as needed.
5892 * Therefore there's no need to enable the input buffer at this
5893 * stage.
5894 */
5895 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5896
5897 /* Mute capture amp left and right */
5898 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5899 /* Set ADC connection select to match default mixer setting - mic
5900 * (on mic1 pin)
5901 */
5902 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
5903
5904 /* Do similar with the second ADC: mute capture input amp and
5905 * set ADC connection to mic to match ALSA's default state.
5906 */
5907 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5908 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
5909
5910 /* Mute all inputs to mixer widget (even unconnected ones) */
5911 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
5912 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
5913 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
5914 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
5915 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
5916 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
5917 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
5918 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
5919
5920 { }
5921};
5922
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005923static struct hda_verb alc260_will_verbs[] = {
5924 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5925 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
5926 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
5927 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
5928 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
5929 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
5930 {}
5931};
5932
5933static struct hda_verb alc260_replacer_672v_verbs[] = {
5934 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
5935 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
5936 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
5937
5938 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
5939 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5940 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
5941
5942 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5943 {}
5944};
5945
5946/* toggle speaker-output according to the hp-jack state */
5947static void alc260_replacer_672v_automute(struct hda_codec *codec)
5948{
5949 unsigned int present;
5950
5951 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
Wu Fengguang864f92b2009-11-18 12:38:02 +08005952 present = snd_hda_jack_detect(codec, 0x0f);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005953 if (present) {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02005954 snd_hda_codec_write_cache(codec, 0x01, 0,
5955 AC_VERB_SET_GPIO_DATA, 1);
5956 snd_hda_codec_write_cache(codec, 0x0f, 0,
5957 AC_VERB_SET_PIN_WIDGET_CONTROL,
5958 PIN_HP);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005959 } else {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02005960 snd_hda_codec_write_cache(codec, 0x01, 0,
5961 AC_VERB_SET_GPIO_DATA, 0);
5962 snd_hda_codec_write_cache(codec, 0x0f, 0,
5963 AC_VERB_SET_PIN_WIDGET_CONTROL,
5964 PIN_OUT);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005965 }
5966}
5967
5968static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
5969 unsigned int res)
5970{
5971 if ((res >> 26) == ALC880_HP_EVENT)
5972 alc260_replacer_672v_automute(codec);
5973}
5974
Kailang Yang3f878302008-08-26 13:02:23 +02005975static struct hda_verb alc260_hp_dc7600_verbs[] = {
5976 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
5977 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
5978 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5979 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5980 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5981 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5982 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5983 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5984 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5985 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5986 {}
5987};
5988
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01005989/* Test configuration for debugging, modelled after the ALC880 test
5990 * configuration.
5991 */
5992#ifdef CONFIG_SND_DEBUG
5993static hda_nid_t alc260_test_dac_nids[1] = {
5994 0x02,
5995};
5996static hda_nid_t alc260_test_adc_nids[2] = {
5997 0x04, 0x05,
5998};
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005999/* For testing the ALC260, each input MUX needs its own definition since
Kailang Yangea1fb292008-08-26 12:58:38 +02006000 * the signal assignments are different. This assumes that the first ADC
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006001 * is NID 0x04.
Jonathan Woithe17e7aec2006-02-28 11:35:18 +01006002 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006003static struct hda_input_mux alc260_test_capture_sources[2] = {
6004 {
6005 .num_items = 7,
6006 .items = {
6007 { "MIC1 pin", 0x0 },
6008 { "MIC2 pin", 0x1 },
6009 { "LINE1 pin", 0x2 },
6010 { "LINE2 pin", 0x3 },
6011 { "CD pin", 0x4 },
6012 { "LINE-OUT pin", 0x5 },
6013 { "HP-OUT pin", 0x6 },
6014 },
6015 },
6016 {
6017 .num_items = 8,
6018 .items = {
6019 { "MIC1 pin", 0x0 },
6020 { "MIC2 pin", 0x1 },
6021 { "LINE1 pin", 0x2 },
6022 { "LINE2 pin", 0x3 },
6023 { "CD pin", 0x4 },
6024 { "Mixer", 0x5 },
6025 { "LINE-OUT pin", 0x6 },
6026 { "HP-OUT pin", 0x7 },
6027 },
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006028 },
6029};
6030static struct snd_kcontrol_new alc260_test_mixer[] = {
6031 /* Output driver widgets */
6032 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
6033 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
6034 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6035 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
6036 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6037 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
6038
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006039 /* Modes for retasking pin widgets
6040 * Note: the ALC260 doesn't seem to act on requests to enable mic
6041 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
6042 * mention this restriction. At this stage it's not clear whether
6043 * this behaviour is intentional or is a hardware bug in chip
6044 * revisions available at least up until early 2006. Therefore for
6045 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
6046 * choices, but if it turns out that the lack of mic bias for these
6047 * NIDs is intentional we could change their modes from
6048 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
6049 */
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006050 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
6051 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
6052 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
6053 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
6054 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
6055 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
6056
6057 /* Loopback mixer controls */
6058 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
6059 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
6060 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
6061 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
6062 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
6063 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
6064 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
6065 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
6066 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6067 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006068 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
6069 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
6070 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
6071 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
Jonathan Woithe5c8f8582006-02-28 11:43:27 +01006072
6073 /* Controls for GPIO pins, assuming they are configured as outputs */
6074 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
6075 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
6076 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
6077 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
6078
Jonathan Woithe92621f12006-02-28 11:47:47 +01006079 /* Switches to allow the digital IO pins to be enabled. The datasheet
6080 * is ambigious as to which NID is which; testing on laptops which
Kailang Yangea1fb292008-08-26 12:58:38 +02006081 * make this output available should provide clarification.
Jonathan Woithe92621f12006-02-28 11:47:47 +01006082 */
6083 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
6084 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
6085
Jonathan Woithef8225f62008-01-08 12:16:54 +01006086 /* A switch allowing EAPD to be enabled. Some laptops seem to use
6087 * this output to turn on an external amplifier.
6088 */
6089 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
6090 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
6091
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006092 { } /* end */
6093};
6094static struct hda_verb alc260_test_init_verbs[] = {
Jonathan Woithe5c8f8582006-02-28 11:43:27 +01006095 /* Enable all GPIOs as outputs with an initial value of 0 */
6096 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
6097 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
6098 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
6099
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006100 /* Enable retasking pins as output, initially without power amp */
6101 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6102 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6103 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6104 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6105 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6106 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6107
Jonathan Woithe92621f12006-02-28 11:47:47 +01006108 /* Disable digital (SPDIF) pins initially, but users can enable
6109 * them via a mixer switch. In the case of SPDIF-out, this initverb
6110 * payload also sets the generation to 0, output to be in "consumer"
6111 * PCM format, copyright asserted, no pre-emphasis and no validity
6112 * control.
6113 */
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006114 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6115 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6116
Kailang Yangea1fb292008-08-26 12:58:38 +02006117 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006118 * OUT1 sum bus when acting as an output.
6119 */
6120 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6121 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
6122 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6123 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
6124
6125 /* Start with output sum widgets muted and their output gains at min */
6126 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6127 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6128 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6129 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6130 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6131 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6132 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6133 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6134 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6135
Jonathan Woithecdcd9262006-02-28 11:36:42 +01006136 /* Unmute retasking pin widget output buffers since the default
6137 * state appears to be output. As the pin mode is changed by the
6138 * user the pin mode control will take care of enabling the pin's
6139 * input/output buffers as needed.
6140 */
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006141 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6142 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6143 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6144 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6145 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6146 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6147 /* Also unmute the mono-out pin widget */
6148 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6149
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006150 /* Mute capture amp left and right */
6151 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithef7ace402006-02-28 11:46:14 +01006152 /* Set ADC connection select to match default mixer setting (mic1
6153 * pin)
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006154 */
6155 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6156
6157 /* Do the same for the second ADC: mute capture input amp and
Jonathan Woithef7ace402006-02-28 11:46:14 +01006158 * set ADC connection to mic1 pin
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006159 */
6160 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6161 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6162
6163 /* Mute all inputs to mixer widget (even unconnected ones) */
6164 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6165 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6166 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6167 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6168 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6169 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6170 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6171 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6172
6173 { }
6174};
6175#endif
6176
Takashi Iwai63300792008-01-24 15:31:36 +01006177#define alc260_pcm_analog_playback alc880_pcm_analog_alt_playback
6178#define alc260_pcm_analog_capture alc880_pcm_analog_capture
Linus Torvalds1da177e2005-04-16 15:20:36 -07006179
Takashi Iwaia3bcba32005-12-06 19:05:29 +01006180#define alc260_pcm_digital_playback alc880_pcm_digital_playback
6181#define alc260_pcm_digital_capture alc880_pcm_digital_capture
6182
Kailang Yangdf694da2005-12-05 19:42:22 +01006183/*
6184 * for BIOS auto-configuration
6185 */
6186
6187static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
Takashi Iwai863b4512008-10-21 17:01:47 +02006188 const char *pfx, int *vol_bits)
Kailang Yangdf694da2005-12-05 19:42:22 +01006189{
6190 hda_nid_t nid_vol;
6191 unsigned long vol_val, sw_val;
Kailang Yangdf694da2005-12-05 19:42:22 +01006192 int err;
6193
6194 if (nid >= 0x0f && nid < 0x11) {
6195 nid_vol = nid - 0x7;
6196 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
6197 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
6198 } else if (nid == 0x11) {
6199 nid_vol = nid - 0x7;
6200 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
6201 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
6202 } else if (nid >= 0x12 && nid <= 0x15) {
6203 nid_vol = 0x08;
6204 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
6205 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
6206 } else
6207 return 0; /* N/A */
Kailang Yangea1fb292008-08-26 12:58:38 +02006208
Takashi Iwai863b4512008-10-21 17:01:47 +02006209 if (!(*vol_bits & (1 << nid_vol))) {
6210 /* first control for the volume widget */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02006211 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
Takashi Iwai863b4512008-10-21 17:01:47 +02006212 if (err < 0)
6213 return err;
6214 *vol_bits |= (1 << nid_vol);
6215 }
Takashi Iwai0afe5f82009-10-02 09:20:00 +02006216 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006217 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006218 return err;
6219 return 1;
6220}
6221
6222/* add playback controls from the parsed DAC table */
6223static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
6224 const struct auto_pin_cfg *cfg)
6225{
6226 hda_nid_t nid;
6227 int err;
Takashi Iwai863b4512008-10-21 17:01:47 +02006228 int vols = 0;
Kailang Yangdf694da2005-12-05 19:42:22 +01006229
6230 spec->multiout.num_dacs = 1;
6231 spec->multiout.dac_nids = spec->private_dac_nids;
6232 spec->multiout.dac_nids[0] = 0x02;
6233
6234 nid = cfg->line_out_pins[0];
6235 if (nid) {
Takashi Iwai23112d62009-08-25 16:07:08 +02006236 const char *pfx;
6237 if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
6238 pfx = "Master";
6239 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
6240 pfx = "Speaker";
6241 else
6242 pfx = "Front";
6243 err = alc260_add_playback_controls(spec, nid, pfx, &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006244 if (err < 0)
6245 return err;
6246 }
6247
Takashi Iwai82bc9552006-03-21 11:24:42 +01006248 nid = cfg->speaker_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006249 if (nid) {
Takashi Iwai863b4512008-10-21 17:01:47 +02006250 err = alc260_add_playback_controls(spec, nid, "Speaker", &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006251 if (err < 0)
6252 return err;
6253 }
6254
Takashi Iwaieb06ed82006-09-20 17:10:27 +02006255 nid = cfg->hp_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006256 if (nid) {
Takashi Iwai863b4512008-10-21 17:01:47 +02006257 err = alc260_add_playback_controls(spec, nid, "Headphone",
6258 &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006259 if (err < 0)
6260 return err;
6261 }
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006262 return 0;
Kailang Yangdf694da2005-12-05 19:42:22 +01006263}
6264
6265/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +02006266static int alc260_auto_create_input_ctls(struct hda_codec *codec,
Kailang Yangdf694da2005-12-05 19:42:22 +01006267 const struct auto_pin_cfg *cfg)
6268{
Takashi Iwai05f5f472009-08-25 13:10:18 +02006269 return alc_auto_create_input_ctls(codec, cfg, 0x07, 0x04, 0x05);
Kailang Yangdf694da2005-12-05 19:42:22 +01006270}
6271
6272static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
6273 hda_nid_t nid, int pin_type,
6274 int sel_idx)
6275{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006276 alc_set_pin_output(codec, nid, pin_type);
Kailang Yangdf694da2005-12-05 19:42:22 +01006277 /* need the manual connection? */
6278 if (nid >= 0x12) {
6279 int idx = nid - 0x12;
6280 snd_hda_codec_write(codec, idx + 0x0b, 0,
6281 AC_VERB_SET_CONNECT_SEL, sel_idx);
Kailang Yangdf694da2005-12-05 19:42:22 +01006282 }
6283}
6284
6285static void alc260_auto_init_multi_out(struct hda_codec *codec)
6286{
6287 struct alc_spec *spec = codec->spec;
6288 hda_nid_t nid;
6289
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006290 nid = spec->autocfg.line_out_pins[0];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02006291 if (nid) {
6292 int pin_type = get_pin_type(spec->autocfg.line_out_type);
6293 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
6294 }
Kailang Yangea1fb292008-08-26 12:58:38 +02006295
Takashi Iwai82bc9552006-03-21 11:24:42 +01006296 nid = spec->autocfg.speaker_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006297 if (nid)
6298 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
6299
Takashi Iwaieb06ed82006-09-20 17:10:27 +02006300 nid = spec->autocfg.hp_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006301 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02006302 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006303}
Kailang Yangdf694da2005-12-05 19:42:22 +01006304
6305#define ALC260_PIN_CD_NID 0x16
6306static void alc260_auto_init_analog_input(struct hda_codec *codec)
6307{
6308 struct alc_spec *spec = codec->spec;
6309 int i;
6310
6311 for (i = 0; i < AUTO_PIN_LAST; i++) {
6312 hda_nid_t nid = spec->autocfg.input_pins[i];
6313 if (nid >= 0x12) {
Takashi Iwai23f0c042009-02-26 13:03:58 +01006314 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +01006315 if (nid != ALC260_PIN_CD_NID &&
6316 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006317 snd_hda_codec_write(codec, nid, 0,
6318 AC_VERB_SET_AMP_GAIN_MUTE,
Kailang Yangdf694da2005-12-05 19:42:22 +01006319 AMP_OUT_MUTE);
6320 }
6321 }
6322}
6323
6324/*
6325 * generic initialization of ADC, input mixers and output mixers
6326 */
6327static struct hda_verb alc260_volume_init_verbs[] = {
6328 /*
6329 * Unmute ADC0-1 and set the default input to mic-in
6330 */
6331 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6332 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6333 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6334 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +02006335
Kailang Yangdf694da2005-12-05 19:42:22 +01006336 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6337 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006338 * Note: PASD motherboards uses the Line In 2 as the input for
6339 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +01006340 */
6341 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02006342 /* mute analog inputs */
6343 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6344 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6345 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6346 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6347 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01006348
6349 /*
6350 * Set up output mixers (0x08 - 0x0a)
6351 */
6352 /* set vol=0 to output mixers */
6353 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6354 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6355 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6356 /* set up input amps for analog loopback */
6357 /* Amp Indices: DAC = 0, mixer = 1 */
6358 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6359 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6360 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6361 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6362 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6363 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +02006364
Kailang Yangdf694da2005-12-05 19:42:22 +01006365 { }
6366};
6367
6368static int alc260_parse_auto_config(struct hda_codec *codec)
6369{
6370 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01006371 int err;
6372 static hda_nid_t alc260_ignore[] = { 0x17, 0 };
6373
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006374 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
6375 alc260_ignore);
6376 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006377 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006378 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
6379 if (err < 0)
Takashi Iwai4a471b72005-12-07 13:56:29 +01006380 return err;
Takashi Iwai603c4012008-07-30 15:01:44 +02006381 if (!spec->kctls.list)
Kailang Yangdf694da2005-12-05 19:42:22 +01006382 return 0; /* can't find valid BIOS pin config */
Takashi Iwai05f5f472009-08-25 13:10:18 +02006383 err = alc260_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006384 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006385 return err;
6386
6387 spec->multiout.max_channels = 2;
6388
Takashi Iwai0852d7a2009-02-11 11:35:15 +01006389 if (spec->autocfg.dig_outs)
Kailang Yangdf694da2005-12-05 19:42:22 +01006390 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
Takashi Iwai603c4012008-07-30 15:01:44 +02006391 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +01006392 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +01006393
Takashi Iwaid88897e2008-10-31 15:01:37 +01006394 add_verb(spec, alc260_volume_init_verbs);
Kailang Yangdf694da2005-12-05 19:42:22 +01006395
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006396 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02006397 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006398
Kailang Yang6227cdc2010-02-25 08:36:52 +01006399 alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02006400
Kailang Yangdf694da2005-12-05 19:42:22 +01006401 return 1;
6402}
6403
Takashi Iwaiae6b8132006-03-03 16:47:17 +01006404/* additional initialization for auto-configuration model */
6405static void alc260_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +01006406{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006407 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01006408 alc260_auto_init_multi_out(codec);
6409 alc260_auto_init_analog_input(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006410 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +02006411 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +01006412}
6413
Takashi Iwaicb53c622007-08-10 17:21:45 +02006414#ifdef CONFIG_SND_HDA_POWER_SAVE
6415static struct hda_amp_list alc260_loopbacks[] = {
6416 { 0x07, HDA_INPUT, 0 },
6417 { 0x07, HDA_INPUT, 1 },
6418 { 0x07, HDA_INPUT, 2 },
6419 { 0x07, HDA_INPUT, 3 },
6420 { 0x07, HDA_INPUT, 4 },
6421 { } /* end */
6422};
6423#endif
6424
Kailang Yangdf694da2005-12-05 19:42:22 +01006425/*
6426 * ALC260 configurations
6427 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006428static const char *alc260_models[ALC260_MODEL_LAST] = {
6429 [ALC260_BASIC] = "basic",
6430 [ALC260_HP] = "hp",
6431 [ALC260_HP_3013] = "hp-3013",
Takashi Iwai2922c9a2008-08-27 18:12:42 +02006432 [ALC260_HP_DC7600] = "hp-dc7600",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006433 [ALC260_FUJITSU_S702X] = "fujitsu",
6434 [ALC260_ACER] = "acer",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006435 [ALC260_WILL] = "will",
6436 [ALC260_REPLACER_672V] = "replacer",
Michael Schwingencc959482009-02-22 18:58:45 +01006437 [ALC260_FAVORIT100] = "favorit100",
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006438#ifdef CONFIG_SND_DEBUG
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006439 [ALC260_TEST] = "test",
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006440#endif
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006441 [ALC260_AUTO] = "auto",
6442};
6443
6444static struct snd_pci_quirk alc260_cfg_tbl[] = {
Jonathan Woithebd869482006-11-28 11:35:52 +01006445 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
Daniel T Chen950200e2009-12-13 14:11:02 -05006446 SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006447 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
Michael Schwingencc959482009-02-22 18:58:45 +01006448 SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
Takashi Iwai9720b712007-03-13 21:46:23 +01006449 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
Takashi Iwai4ac55982009-11-10 16:08:45 +01006450 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006451 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
Jaroslav Kysela34ec8a02008-07-10 14:49:19 +02006452 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
Kailang Yang3f878302008-08-26 13:02:23 +02006453 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006454 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
6455 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
6456 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
6457 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
6458 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
6459 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
6460 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
6461 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
6462 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006463 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01006464 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
Takashi Iwai16ded522005-06-10 19:58:24 +02006465 {}
6466};
6467
Kailang Yangdf694da2005-12-05 19:42:22 +01006468static struct alc_config_preset alc260_presets[] = {
6469 [ALC260_BASIC] = {
6470 .mixers = { alc260_base_output_mixer,
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01006471 alc260_input_mixer },
Kailang Yangdf694da2005-12-05 19:42:22 +01006472 .init_verbs = { alc260_init_verbs },
6473 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6474 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006475 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
Kailang Yangdf694da2005-12-05 19:42:22 +01006476 .adc_nids = alc260_adc_nids,
6477 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6478 .channel_mode = alc260_modes,
6479 .input_mux = &alc260_capture_source,
6480 },
6481 [ALC260_HP] = {
Takashi Iwaibec15c32008-01-28 18:16:30 +01006482 .mixers = { alc260_hp_output_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006483 alc260_input_mixer },
Takashi Iwaibec15c32008-01-28 18:16:30 +01006484 .init_verbs = { alc260_init_verbs,
6485 alc260_hp_unsol_verbs },
Kailang Yangdf694da2005-12-05 19:42:22 +01006486 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6487 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006488 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6489 .adc_nids = alc260_adc_nids_alt,
Kailang Yangdf694da2005-12-05 19:42:22 +01006490 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6491 .channel_mode = alc260_modes,
6492 .input_mux = &alc260_capture_source,
Takashi Iwaibec15c32008-01-28 18:16:30 +01006493 .unsol_event = alc260_hp_unsol_event,
6494 .init_hook = alc260_hp_automute,
Kailang Yangdf694da2005-12-05 19:42:22 +01006495 },
Kailang Yang3f878302008-08-26 13:02:23 +02006496 [ALC260_HP_DC7600] = {
6497 .mixers = { alc260_hp_dc7600_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006498 alc260_input_mixer },
Kailang Yang3f878302008-08-26 13:02:23 +02006499 .init_verbs = { alc260_init_verbs,
6500 alc260_hp_dc7600_verbs },
6501 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6502 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006503 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6504 .adc_nids = alc260_adc_nids_alt,
Kailang Yang3f878302008-08-26 13:02:23 +02006505 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6506 .channel_mode = alc260_modes,
6507 .input_mux = &alc260_capture_source,
6508 .unsol_event = alc260_hp_3012_unsol_event,
6509 .init_hook = alc260_hp_3012_automute,
6510 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006511 [ALC260_HP_3013] = {
6512 .mixers = { alc260_hp_3013_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006513 alc260_input_mixer },
Takashi Iwaibec15c32008-01-28 18:16:30 +01006514 .init_verbs = { alc260_hp_3013_init_verbs,
6515 alc260_hp_3013_unsol_verbs },
Kailang Yangdf694da2005-12-05 19:42:22 +01006516 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6517 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006518 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6519 .adc_nids = alc260_adc_nids_alt,
Kailang Yangdf694da2005-12-05 19:42:22 +01006520 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6521 .channel_mode = alc260_modes,
6522 .input_mux = &alc260_capture_source,
Takashi Iwaibec15c32008-01-28 18:16:30 +01006523 .unsol_event = alc260_hp_3013_unsol_event,
6524 .init_hook = alc260_hp_3013_automute,
Kailang Yangdf694da2005-12-05 19:42:22 +01006525 },
6526 [ALC260_FUJITSU_S702X] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006527 .mixers = { alc260_fujitsu_mixer },
Kailang Yangdf694da2005-12-05 19:42:22 +01006528 .init_verbs = { alc260_fujitsu_init_verbs },
6529 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6530 .dac_nids = alc260_dac_nids,
Jonathan Woithed57fdac2006-02-28 11:38:35 +01006531 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6532 .adc_nids = alc260_dual_adc_nids,
Kailang Yangdf694da2005-12-05 19:42:22 +01006533 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6534 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006535 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
6536 .input_mux = alc260_fujitsu_capture_sources,
Kailang Yangdf694da2005-12-05 19:42:22 +01006537 },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006538 [ALC260_ACER] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006539 .mixers = { alc260_acer_mixer },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006540 .init_verbs = { alc260_acer_init_verbs },
6541 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6542 .dac_nids = alc260_dac_nids,
6543 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6544 .adc_nids = alc260_dual_adc_nids,
6545 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6546 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006547 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
6548 .input_mux = alc260_acer_capture_sources,
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006549 },
Michael Schwingencc959482009-02-22 18:58:45 +01006550 [ALC260_FAVORIT100] = {
6551 .mixers = { alc260_favorit100_mixer },
6552 .init_verbs = { alc260_favorit100_init_verbs },
6553 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6554 .dac_nids = alc260_dac_nids,
6555 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6556 .adc_nids = alc260_dual_adc_nids,
6557 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6558 .channel_mode = alc260_modes,
6559 .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
6560 .input_mux = alc260_favorit100_capture_sources,
6561 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006562 [ALC260_WILL] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006563 .mixers = { alc260_will_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006564 .init_verbs = { alc260_init_verbs, alc260_will_verbs },
6565 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6566 .dac_nids = alc260_dac_nids,
6567 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
6568 .adc_nids = alc260_adc_nids,
6569 .dig_out_nid = ALC260_DIGOUT_NID,
6570 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6571 .channel_mode = alc260_modes,
6572 .input_mux = &alc260_capture_source,
6573 },
6574 [ALC260_REPLACER_672V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006575 .mixers = { alc260_replacer_672v_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006576 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
6577 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6578 .dac_nids = alc260_dac_nids,
6579 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
6580 .adc_nids = alc260_adc_nids,
6581 .dig_out_nid = ALC260_DIGOUT_NID,
6582 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6583 .channel_mode = alc260_modes,
6584 .input_mux = &alc260_capture_source,
6585 .unsol_event = alc260_replacer_672v_unsol_event,
6586 .init_hook = alc260_replacer_672v_automute,
6587 },
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006588#ifdef CONFIG_SND_DEBUG
6589 [ALC260_TEST] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006590 .mixers = { alc260_test_mixer },
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006591 .init_verbs = { alc260_test_init_verbs },
6592 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
6593 .dac_nids = alc260_test_dac_nids,
6594 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
6595 .adc_nids = alc260_test_adc_nids,
6596 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6597 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006598 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
6599 .input_mux = alc260_test_capture_sources,
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006600 },
6601#endif
Kailang Yangdf694da2005-12-05 19:42:22 +01006602};
6603
Linus Torvalds1da177e2005-04-16 15:20:36 -07006604static int patch_alc260(struct hda_codec *codec)
6605{
6606 struct alc_spec *spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01006607 int err, board_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006608
Takashi Iwaie560d8d2005-09-09 14:21:46 +02006609 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006610 if (spec == NULL)
6611 return -ENOMEM;
6612
6613 codec->spec = spec;
6614
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006615 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
6616 alc260_models,
6617 alc260_cfg_tbl);
6618 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02006619 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
Takashi Iwai6c627f32009-05-18 12:33:36 +02006620 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +01006621 board_config = ALC260_AUTO;
Takashi Iwai16ded522005-06-10 19:58:24 +02006622 }
6623
Kailang Yangdf694da2005-12-05 19:42:22 +01006624 if (board_config == ALC260_AUTO) {
6625 /* automatic parse from the BIOS config */
6626 err = alc260_parse_auto_config(codec);
6627 if (err < 0) {
6628 alc_free(codec);
6629 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006630 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02006631 printk(KERN_INFO
6632 "hda_codec: Cannot set up configuration "
6633 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +01006634 board_config = ALC260_BASIC;
6635 }
Takashi Iwai16ded522005-06-10 19:58:24 +02006636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006637
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09006638 err = snd_hda_attach_beep_device(codec, 0x1);
6639 if (err < 0) {
6640 alc_free(codec);
6641 return err;
6642 }
6643
Kailang Yangdf694da2005-12-05 19:42:22 +01006644 if (board_config != ALC260_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02006645 setup_preset(codec, &alc260_presets[board_config]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006646
Linus Torvalds1da177e2005-04-16 15:20:36 -07006647 spec->stream_analog_playback = &alc260_pcm_analog_playback;
6648 spec->stream_analog_capture = &alc260_pcm_analog_capture;
6649
Takashi Iwaia3bcba32005-12-06 19:05:29 +01006650 spec->stream_digital_playback = &alc260_pcm_digital_playback;
6651 spec->stream_digital_capture = &alc260_pcm_digital_capture;
6652
Takashi Iwai4ef0ef12008-11-03 17:47:49 +01006653 if (!spec->adc_nids && spec->input_mux) {
6654 /* check whether NID 0x04 is valid */
6655 unsigned int wcap = get_wcaps(codec, 0x04);
Takashi Iwaia22d5432009-07-27 12:54:26 +02006656 wcap = get_wcaps_type(wcap);
Takashi Iwai4ef0ef12008-11-03 17:47:49 +01006657 /* get type */
6658 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
6659 spec->adc_nids = alc260_adc_nids_alt;
6660 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
6661 } else {
6662 spec->adc_nids = alc260_adc_nids;
6663 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
6664 }
6665 }
Takashi Iwaib59bdf32009-08-11 09:47:30 +02006666 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01006667 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006668
Takashi Iwai2134ea42008-01-10 16:53:55 +01006669 spec->vmaster_nid = 0x08;
6670
Linus Torvalds1da177e2005-04-16 15:20:36 -07006671 codec->patch_ops = alc_patch_ops;
Kailang Yangdf694da2005-12-05 19:42:22 +01006672 if (board_config == ALC260_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01006673 spec->init_hook = alc260_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +02006674#ifdef CONFIG_SND_HDA_POWER_SAVE
6675 if (!spec->loopback.amplist)
6676 spec->loopback.amplist = alc260_loopbacks;
6677#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006678
6679 return 0;
6680}
6681
Takashi Iwaie9edcee2005-06-13 14:16:38 +02006682
Linus Torvalds1da177e2005-04-16 15:20:36 -07006683/*
Takashi Iwai49535502009-06-30 15:28:30 +02006684 * ALC882/883/885/888/889 support
Linus Torvalds1da177e2005-04-16 15:20:36 -07006685 *
6686 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
6687 * configuration. Each pin widget can choose any input DACs and a mixer.
6688 * Each ADC is connected from a mixer of all inputs. This makes possible
6689 * 6-channel independent captures.
6690 *
6691 * In addition, an independent DAC for the multi-playback (not used in this
6692 * driver yet).
6693 */
Kailang Yangdf694da2005-12-05 19:42:22 +01006694#define ALC882_DIGOUT_NID 0x06
6695#define ALC882_DIGIN_NID 0x0a
Takashi Iwai49535502009-06-30 15:28:30 +02006696#define ALC883_DIGOUT_NID ALC882_DIGOUT_NID
6697#define ALC883_DIGIN_NID ALC882_DIGIN_NID
6698#define ALC1200_DIGOUT_NID 0x10
6699
Linus Torvalds1da177e2005-04-16 15:20:36 -07006700
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01006701static struct hda_channel_mode alc882_ch_modes[1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006702 { 8, NULL }
6703};
6704
Takashi Iwai49535502009-06-30 15:28:30 +02006705/* DACs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006706static hda_nid_t alc882_dac_nids[4] = {
6707 /* front, rear, clfe, rear_surr */
6708 0x02, 0x03, 0x04, 0x05
6709};
Takashi Iwai49535502009-06-30 15:28:30 +02006710#define alc883_dac_nids alc882_dac_nids
Linus Torvalds1da177e2005-04-16 15:20:36 -07006711
Takashi Iwai49535502009-06-30 15:28:30 +02006712/* ADCs */
Kailang Yangdf694da2005-12-05 19:42:22 +01006713#define alc882_adc_nids alc880_adc_nids
6714#define alc882_adc_nids_alt alc880_adc_nids_alt
Takashi Iwai49535502009-06-30 15:28:30 +02006715#define alc883_adc_nids alc882_adc_nids_alt
6716static hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
6717static hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
6718#define alc889_adc_nids alc880_adc_nids
Linus Torvalds1da177e2005-04-16 15:20:36 -07006719
Takashi Iwaie1406342008-02-11 18:32:32 +01006720static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
6721static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
Takashi Iwai49535502009-06-30 15:28:30 +02006722#define alc883_capsrc_nids alc882_capsrc_nids_alt
6723static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
6724#define alc889_capsrc_nids alc882_capsrc_nids
Takashi Iwaie1406342008-02-11 18:32:32 +01006725
Linus Torvalds1da177e2005-04-16 15:20:36 -07006726/* input MUX */
6727/* FIXME: should be a matrix-type input source selection */
6728
6729static struct hda_input_mux alc882_capture_source = {
6730 .num_items = 4,
6731 .items = {
6732 { "Mic", 0x0 },
6733 { "Front Mic", 0x1 },
6734 { "Line", 0x2 },
6735 { "CD", 0x4 },
6736 },
6737};
Kacper Szczesniak41d55452009-05-07 12:47:43 +02006738
Takashi Iwai49535502009-06-30 15:28:30 +02006739#define alc883_capture_source alc882_capture_source
6740
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02006741static struct hda_input_mux alc889_capture_source = {
6742 .num_items = 3,
6743 .items = {
6744 { "Front Mic", 0x0 },
6745 { "Mic", 0x3 },
6746 { "Line", 0x2 },
6747 },
6748};
6749
Kacper Szczesniak41d55452009-05-07 12:47:43 +02006750static struct hda_input_mux mb5_capture_source = {
6751 .num_items = 3,
6752 .items = {
6753 { "Mic", 0x1 },
6754 { "Line", 0x2 },
6755 { "CD", 0x4 },
6756 },
6757};
6758
Luke Yelaviche458b1f2010-02-12 16:28:29 +11006759static struct hda_input_mux macmini3_capture_source = {
6760 .num_items = 2,
6761 .items = {
6762 { "Line", 0x2 },
6763 { "CD", 0x4 },
6764 },
6765};
6766
Takashi Iwai49535502009-06-30 15:28:30 +02006767static struct hda_input_mux alc883_3stack_6ch_intel = {
6768 .num_items = 4,
6769 .items = {
6770 { "Mic", 0x1 },
6771 { "Front Mic", 0x0 },
6772 { "Line", 0x2 },
6773 { "CD", 0x4 },
6774 },
6775};
6776
6777static struct hda_input_mux alc883_lenovo_101e_capture_source = {
6778 .num_items = 2,
6779 .items = {
6780 { "Mic", 0x1 },
6781 { "Line", 0x2 },
6782 },
6783};
6784
6785static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
6786 .num_items = 4,
6787 .items = {
6788 { "Mic", 0x0 },
6789 { "iMic", 0x1 },
6790 { "Line", 0x2 },
6791 { "CD", 0x4 },
6792 },
6793};
6794
6795static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
6796 .num_items = 2,
6797 .items = {
6798 { "Mic", 0x0 },
6799 { "Int Mic", 0x1 },
6800 },
6801};
6802
6803static struct hda_input_mux alc883_lenovo_sky_capture_source = {
6804 .num_items = 3,
6805 .items = {
6806 { "Mic", 0x0 },
6807 { "Front Mic", 0x1 },
6808 { "Line", 0x4 },
6809 },
6810};
6811
6812static struct hda_input_mux alc883_asus_eee1601_capture_source = {
6813 .num_items = 2,
6814 .items = {
6815 { "Mic", 0x0 },
6816 { "Line", 0x2 },
6817 },
6818};
6819
6820static struct hda_input_mux alc889A_mb31_capture_source = {
6821 .num_items = 2,
6822 .items = {
6823 { "Mic", 0x0 },
6824 /* Front Mic (0x01) unused */
6825 { "Line", 0x2 },
6826 /* Line 2 (0x03) unused */
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02006827 /* CD (0x04) unused? */
Takashi Iwai49535502009-06-30 15:28:30 +02006828 },
6829};
6830
6831/*
6832 * 2ch mode
6833 */
6834static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
6835 { 2, NULL }
6836};
6837
Kailang Yangdf694da2005-12-05 19:42:22 +01006838/*
Kailang Yang272a5272007-05-14 11:00:38 +02006839 * 2ch mode
6840 */
6841static struct hda_verb alc882_3ST_ch2_init[] = {
6842 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6843 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6844 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
6845 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6846 { } /* end */
6847};
6848
6849/*
Takashi Iwai49535502009-06-30 15:28:30 +02006850 * 4ch mode
6851 */
6852static struct hda_verb alc882_3ST_ch4_init[] = {
6853 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6854 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6855 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6856 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6857 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6858 { } /* end */
6859};
6860
6861/*
Kailang Yang272a5272007-05-14 11:00:38 +02006862 * 6ch mode
6863 */
6864static struct hda_verb alc882_3ST_ch6_init[] = {
6865 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6866 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6867 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
6868 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6869 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6870 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6871 { } /* end */
6872};
6873
Takashi Iwai49535502009-06-30 15:28:30 +02006874static struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
Kailang Yang272a5272007-05-14 11:00:38 +02006875 { 2, alc882_3ST_ch2_init },
Takashi Iwai49535502009-06-30 15:28:30 +02006876 { 4, alc882_3ST_ch4_init },
Kailang Yang272a5272007-05-14 11:00:38 +02006877 { 6, alc882_3ST_ch6_init },
6878};
6879
Takashi Iwai49535502009-06-30 15:28:30 +02006880#define alc883_3ST_6ch_modes alc882_3ST_6ch_modes
6881
Kailang Yang272a5272007-05-14 11:00:38 +02006882/*
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04306883 * 2ch mode
6884 */
6885static struct hda_verb alc883_3ST_ch2_clevo_init[] = {
6886 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
6887 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6888 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6889 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
6890 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6891 { } /* end */
6892};
6893
6894/*
6895 * 4ch mode
6896 */
6897static struct hda_verb alc883_3ST_ch4_clevo_init[] = {
6898 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6899 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
6900 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
6901 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6902 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6903 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6904 { } /* end */
6905};
6906
6907/*
6908 * 6ch mode
6909 */
6910static struct hda_verb alc883_3ST_ch6_clevo_init[] = {
6911 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6912 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6913 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6914 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
6915 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6916 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6917 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6918 { } /* end */
6919};
6920
6921static struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
6922 { 2, alc883_3ST_ch2_clevo_init },
6923 { 4, alc883_3ST_ch4_clevo_init },
6924 { 6, alc883_3ST_ch6_clevo_init },
6925};
6926
6927
6928/*
Kailang Yangdf694da2005-12-05 19:42:22 +01006929 * 6ch mode
6930 */
6931static struct hda_verb alc882_sixstack_ch6_init[] = {
6932 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
6933 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6934 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6935 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6936 { } /* end */
6937};
6938
6939/*
6940 * 8ch mode
6941 */
6942static struct hda_verb alc882_sixstack_ch8_init[] = {
6943 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6944 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6945 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6946 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6947 { } /* end */
6948};
6949
6950static struct hda_channel_mode alc882_sixstack_modes[2] = {
6951 { 6, alc882_sixstack_ch6_init },
6952 { 8, alc882_sixstack_ch8_init },
6953};
6954
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08006955
6956/* Macbook Air 2,1 */
6957
6958static struct hda_channel_mode alc885_mba21_ch_modes[1] = {
6959 { 2, NULL },
6960};
6961
Takashi Iwai87350ad2007-08-16 18:19:38 +02006962/*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04006963 * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
Takashi Iwai87350ad2007-08-16 18:19:38 +02006964 */
6965
6966/*
6967 * 2ch mode
6968 */
6969static struct hda_verb alc885_mbp_ch2_init[] = {
6970 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
6971 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6972 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6973 { } /* end */
6974};
6975
6976/*
Takashi Iwaia3f730a2009-08-31 08:15:26 +02006977 * 4ch mode
Takashi Iwai87350ad2007-08-16 18:19:38 +02006978 */
Takashi Iwaia3f730a2009-08-31 08:15:26 +02006979static struct hda_verb alc885_mbp_ch4_init[] = {
Takashi Iwai87350ad2007-08-16 18:19:38 +02006980 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
6981 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6982 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
6983 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6984 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6985 { } /* end */
6986};
6987
Takashi Iwaia3f730a2009-08-31 08:15:26 +02006988static struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
Takashi Iwai87350ad2007-08-16 18:19:38 +02006989 { 2, alc885_mbp_ch2_init },
Takashi Iwaia3f730a2009-08-31 08:15:26 +02006990 { 4, alc885_mbp_ch4_init },
Takashi Iwai87350ad2007-08-16 18:19:38 +02006991};
6992
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02006993/*
6994 * 2ch
6995 * Speakers/Woofer/HP = Front
6996 * LineIn = Input
6997 */
6998static struct hda_verb alc885_mb5_ch2_init[] = {
6999 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7000 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7001 { } /* end */
7002};
7003
7004/*
7005 * 6ch mode
7006 * Speakers/HP = Front
7007 * Woofer = LFE
7008 * LineIn = Surround
7009 */
7010static struct hda_verb alc885_mb5_ch6_init[] = {
7011 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7012 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7013 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
7014 { } /* end */
7015};
7016
7017static struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
7018 { 2, alc885_mb5_ch2_init },
7019 { 6, alc885_mb5_ch6_init },
7020};
Takashi Iwai87350ad2007-08-16 18:19:38 +02007021
Takashi Iwaid01aecd2010-02-23 08:07:15 +01007022#define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes
Takashi Iwai49535502009-06-30 15:28:30 +02007023
7024/*
7025 * 2ch mode
7026 */
7027static struct hda_verb alc883_4ST_ch2_init[] = {
7028 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7029 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7030 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7031 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7032 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7033 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7034 { } /* end */
7035};
7036
7037/*
7038 * 4ch mode
7039 */
7040static struct hda_verb alc883_4ST_ch4_init[] = {
7041 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7042 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7043 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7044 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7045 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7046 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7047 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7048 { } /* end */
7049};
7050
7051/*
7052 * 6ch mode
7053 */
7054static struct hda_verb alc883_4ST_ch6_init[] = {
7055 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7056 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7057 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7058 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7059 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7060 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7061 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7062 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7063 { } /* end */
7064};
7065
7066/*
7067 * 8ch mode
7068 */
7069static struct hda_verb alc883_4ST_ch8_init[] = {
7070 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7071 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7072 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7073 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7074 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7075 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7076 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7077 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7078 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7079 { } /* end */
7080};
7081
7082static struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
7083 { 2, alc883_4ST_ch2_init },
7084 { 4, alc883_4ST_ch4_init },
7085 { 6, alc883_4ST_ch6_init },
7086 { 8, alc883_4ST_ch8_init },
7087};
7088
7089
7090/*
7091 * 2ch mode
7092 */
7093static struct hda_verb alc883_3ST_ch2_intel_init[] = {
7094 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7095 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7096 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7097 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7098 { } /* end */
7099};
7100
7101/*
7102 * 4ch mode
7103 */
7104static struct hda_verb alc883_3ST_ch4_intel_init[] = {
7105 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7106 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7107 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7108 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7109 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7110 { } /* end */
7111};
7112
7113/*
7114 * 6ch mode
7115 */
7116static struct hda_verb alc883_3ST_ch6_intel_init[] = {
7117 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7118 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7119 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
7120 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7121 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7122 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7123 { } /* end */
7124};
7125
7126static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
7127 { 2, alc883_3ST_ch2_intel_init },
7128 { 4, alc883_3ST_ch4_intel_init },
7129 { 6, alc883_3ST_ch6_intel_init },
7130};
7131
7132/*
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007133 * 2ch mode
7134 */
7135static struct hda_verb alc889_ch2_intel_init[] = {
7136 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7137 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
7138 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
7139 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
7140 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7141 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7142 { } /* end */
7143};
7144
7145/*
Takashi Iwai49535502009-06-30 15:28:30 +02007146 * 6ch mode
7147 */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007148static struct hda_verb alc889_ch6_intel_init[] = {
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007149 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7150 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
7151 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
7152 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7153 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007154 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7155 { } /* end */
7156};
7157
7158/*
7159 * 8ch mode
7160 */
7161static struct hda_verb alc889_ch8_intel_init[] = {
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007162 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7163 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
7164 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
7165 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7166 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007167 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7168 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007169 { } /* end */
7170};
7171
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007172static struct hda_channel_mode alc889_8ch_intel_modes[3] = {
7173 { 2, alc889_ch2_intel_init },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007174 { 6, alc889_ch6_intel_init },
7175 { 8, alc889_ch8_intel_init },
7176};
7177
7178/*
7179 * 6ch mode
7180 */
Takashi Iwai49535502009-06-30 15:28:30 +02007181static struct hda_verb alc883_sixstack_ch6_init[] = {
7182 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7183 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7184 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7185 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7186 { } /* end */
7187};
7188
7189/*
7190 * 8ch mode
7191 */
7192static struct hda_verb alc883_sixstack_ch8_init[] = {
7193 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7194 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7195 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7196 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7197 { } /* end */
7198};
7199
7200static struct hda_channel_mode alc883_sixstack_modes[2] = {
7201 { 6, alc883_sixstack_ch6_init },
7202 { 8, alc883_sixstack_ch8_init },
7203};
7204
7205
Linus Torvalds1da177e2005-04-16 15:20:36 -07007206/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
7207 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
7208 */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01007209static struct snd_kcontrol_new alc882_base_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02007210 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007211 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007212 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007213 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007214 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
7215 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007216 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
7217 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007218 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007219 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007220 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7221 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7222 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7223 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7224 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7225 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01007226 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007227 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7228 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01007229 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007230 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007231 { } /* end */
7232};
7233
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08007234/* Macbook Air 2,1 same control for HP and internal Speaker */
7235
7236static struct snd_kcontrol_new alc885_mba21_mixer[] = {
7237 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7238 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
7239 { }
7240};
7241
7242
Takashi Iwai87350ad2007-08-16 18:19:38 +02007243static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007244 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7245 HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
7246 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7247 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
7248 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01007249 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7250 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwai87350ad2007-08-16 18:19:38 +02007251 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
7252 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01007253 HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
Takashi Iwai87350ad2007-08-16 18:19:38 +02007254 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
7255 { } /* end */
7256};
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007257
7258static struct snd_kcontrol_new alc885_mb5_mixer[] = {
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007259 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7260 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
7261 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
7262 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
7263 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7264 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
Alex Murraya76221d2010-01-13 23:15:03 +10307265 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
7266 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007267 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7268 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7269 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
7270 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
7271 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
7272 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0x00, HDA_INPUT),
7273 { } /* end */
7274};
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007275
Luke Yelaviche458b1f2010-02-12 16:28:29 +11007276static struct snd_kcontrol_new alc885_macmini3_mixer[] = {
7277 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7278 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
7279 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
7280 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
7281 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7282 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
7283 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
7284 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
7285 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
7286 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
7287 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
7288 { } /* end */
7289};
7290
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08007291static struct snd_kcontrol_new alc885_imac91_mixer[] = {
7292 HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7293 HDA_BIND_MUTE ("Line-Out Playback Switch", 0x0c, 0x02, HDA_INPUT),
7294 HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),
7295 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
7296 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7297 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7298 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
7299 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
7300 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
7301 { } /* end */
7302};
7303
7304
Kailang Yangbdd148a2007-05-08 15:19:08 +02007305static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
7306 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7307 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7308 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7309 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7310 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7311 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7312 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7313 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7314 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangbdd148a2007-05-08 15:19:08 +02007315 { } /* end */
7316};
7317
Kailang Yang272a5272007-05-14 11:00:38 +02007318static struct snd_kcontrol_new alc882_targa_mixer[] = {
7319 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7320 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7321 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7322 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7323 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7324 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7325 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7326 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7327 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai96fe7cc2007-09-07 10:57:44 +02007328 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007329 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7330 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai96fe7cc2007-09-07 10:57:44 +02007331 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007332 { } /* end */
7333};
7334
7335/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
7336 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
7337 */
7338static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
7339 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7340 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7341 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7342 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
7343 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7344 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7345 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7346 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7347 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
7348 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
7349 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7350 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai96fe7cc2007-09-07 10:57:44 +02007351 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007352 { } /* end */
7353};
7354
Takashi Iwai914759b2007-09-06 14:52:04 +02007355static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
7356 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7357 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7358 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7359 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7360 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7361 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7362 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7363 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7364 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7365 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai914759b2007-09-06 14:52:04 +02007366 { } /* end */
7367};
7368
Kailang Yangdf694da2005-12-05 19:42:22 +01007369static struct snd_kcontrol_new alc882_chmode_mixer[] = {
7370 {
7371 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7372 .name = "Channel Mode",
7373 .info = alc_ch_mode_info,
7374 .get = alc_ch_mode_get,
7375 .put = alc_ch_mode_put,
7376 },
7377 { } /* end */
7378};
7379
Takashi Iwai49535502009-06-30 15:28:30 +02007380static struct hda_verb alc882_base_init_verbs[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007381 /* Front mixer: unmute input/output amp left and right (volume = 0) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007382 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7383 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007384 /* Rear mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007385 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7386 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007387 /* CLFE mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007388 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7389 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007390 /* Side mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007391 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7392 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007393
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007394 /* Front Pin: output 0 (0x0c) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007395 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007396 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007397 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007398 /* Rear Pin: output 1 (0x0d) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007399 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007400 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007401 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007402 /* CLFE Pin: output 2 (0x0e) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007403 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007404 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007405 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007406 /* Side Pin: output 3 (0x0f) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007407 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007408 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007409 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007410 /* Mic (rear) pin: input vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02007411 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007412 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7413 /* Front Mic pin: input vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02007414 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007415 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7416 /* Line In pin: input */
Takashi Iwai05acb862005-06-10 19:50:25 +02007417 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007418 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7419 /* Line-2 In: Headphone output (output 0 - 0x0c) */
7420 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7421 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7422 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007423 /* CD pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02007424 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007425
7426 /* FIXME: use matrix-type input source selection */
7427 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007428 /* Input mixer2 */
Takashi Iwai05acb862005-06-10 19:50:25 +02007429 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007430 /* Input mixer3 */
Takashi Iwai05acb862005-06-10 19:50:25 +02007431 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai05acb862005-06-10 19:50:25 +02007432 /* ADC2: mute amp left and right */
7433 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02007434 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02007435 /* ADC3: mute amp left and right */
7436 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02007437 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007438
7439 { }
7440};
7441
Takashi Iwai49535502009-06-30 15:28:30 +02007442static struct hda_verb alc882_adc1_init_verbs[] = {
7443 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7444 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7445 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7446 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7447 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7448 /* ADC1: mute amp left and right */
7449 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7450 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7451 { }
7452};
7453
Takashi Iwai4b146cb2006-07-28 14:42:36 +02007454static struct hda_verb alc882_eapd_verbs[] = {
7455 /* change to EAPD mode */
7456 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01007457 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02007458 { }
Takashi Iwai4b146cb2006-07-28 14:42:36 +02007459};
7460
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007461static struct hda_verb alc889_eapd_verbs[] = {
7462 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
7463 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
7464 { }
7465};
7466
Wu Fengguang6732bd02009-07-30 09:19:14 +02007467static struct hda_verb alc_hp15_unsol_verbs[] = {
7468 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
7469 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7470 {}
7471};
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007472
7473static struct hda_verb alc885_init_verbs[] = {
7474 /* Front mixer: unmute input/output amp left and right (volume = 0) */
Kailang Yang88102f32010-02-04 14:12:58 +01007475 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7476 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007477 /* Rear mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007478 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7479 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007480 /* CLFE mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007481 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7482 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007483 /* Side mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007484 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7485 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007486
7487 /* Front HP Pin: output 0 (0x0c) */
Wu Fengguang6732bd02009-07-30 09:19:14 +02007488 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007489 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7490 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7491 /* Front Pin: output 0 (0x0c) */
7492 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7493 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7494 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7495 /* Rear Pin: output 1 (0x0d) */
7496 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7497 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7498 {0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
7499 /* CLFE Pin: output 2 (0x0e) */
7500 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7501 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7502 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
7503 /* Side Pin: output 3 (0x0f) */
7504 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7505 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7506 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
7507 /* Mic (rear) pin: input vref at 80% */
7508 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7509 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7510 /* Front Mic pin: input vref at 80% */
7511 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7512 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7513 /* Line In pin: input */
7514 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7515 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7516
7517 /* Mixer elements: 0x18, , 0x1a, 0x1b */
7518 /* Input mixer1 */
Kailang Yang88102f32010-02-04 14:12:58 +01007519 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007520 /* Input mixer2 */
7521 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007522 /* Input mixer3 */
Kailang Yang88102f32010-02-04 14:12:58 +01007523 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007524 /* ADC2: mute amp left and right */
7525 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7526 /* ADC3: mute amp left and right */
7527 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7528
7529 { }
7530};
7531
7532static struct hda_verb alc885_init_input_verbs[] = {
7533 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7534 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7535 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7536 { }
7537};
7538
7539
7540/* Unmute Selector 24h and set the default input to front mic */
7541static struct hda_verb alc889_init_input_verbs[] = {
7542 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
7543 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7544 { }
7545};
7546
7547
Takashi Iwai49535502009-06-30 15:28:30 +02007548#define alc883_init_verbs alc882_base_init_verbs
7549
Tobin Davis9102cd12006-12-15 10:02:12 +01007550/* Mac Pro test */
7551static struct snd_kcontrol_new alc882_macpro_mixer[] = {
7552 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7553 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7554 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
7555 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
7556 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01007557 /* FIXME: this looks suspicious...
Jaroslav Kyselad355c82a2009-11-03 15:47:25 +01007558 HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
7559 HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01007560 */
Tobin Davis9102cd12006-12-15 10:02:12 +01007561 { } /* end */
7562};
7563
7564static struct hda_verb alc882_macpro_init_verbs[] = {
7565 /* Front mixer: unmute input/output amp left and right (volume = 0) */
7566 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7567 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7568 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7569 /* Front Pin: output 0 (0x0c) */
7570 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7571 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7572 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7573 /* Front Mic pin: input vref at 80% */
7574 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7575 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7576 /* Speaker: output */
7577 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7578 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7579 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
7580 /* Headphone output (output 0 - 0x0c) */
7581 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7582 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7583 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7584
7585 /* FIXME: use matrix-type input source selection */
7586 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7587 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7588 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7589 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7590 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7591 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7592 /* Input mixer2 */
7593 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7594 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7595 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7596 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7597 /* Input mixer3 */
7598 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7599 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7600 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7601 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7602 /* ADC1: mute amp left and right */
7603 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7604 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7605 /* ADC2: mute amp left and right */
7606 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7607 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7608 /* ADC3: mute amp left and right */
7609 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7610 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7611
7612 { }
7613};
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02007614
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007615/* Macbook 5,1 */
7616static struct hda_verb alc885_mb5_init_verbs[] = {
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007617 /* DACs */
7618 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7619 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7620 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7621 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007622 /* Front mixer */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007623 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7624 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7625 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007626 /* Surround mixer */
7627 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7628 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7629 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7630 /* LFE mixer */
7631 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7632 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7633 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7634 /* HP mixer */
7635 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7636 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7637 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7638 /* Front Pin (0x0c) */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007639 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
7640 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007641 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7642 /* LFE Pin (0x0e) */
7643 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
7644 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7645 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
7646 /* HP Pin (0x0f) */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007647 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7648 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007649 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
Alex Murraya76221d2010-01-13 23:15:03 +10307650 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007651 /* Front Mic pin: input vref at 80% */
7652 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7653 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7654 /* Line In pin */
7655 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7656 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7657
7658 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7659 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7660 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7661 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7662 { }
7663};
7664
Luke Yelaviche458b1f2010-02-12 16:28:29 +11007665/* Macmini 3,1 */
7666static struct hda_verb alc885_macmini3_init_verbs[] = {
7667 /* DACs */
7668 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7669 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7670 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7671 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7672 /* Front mixer */
7673 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7674 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7675 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7676 /* Surround mixer */
7677 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7678 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7679 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7680 /* LFE mixer */
7681 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7682 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7683 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7684 /* HP mixer */
7685 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7686 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7687 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7688 /* Front Pin (0x0c) */
7689 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
7690 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7691 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7692 /* LFE Pin (0x0e) */
7693 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
7694 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7695 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
7696 /* HP Pin (0x0f) */
7697 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7698 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7699 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
7700 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7701 /* Line In pin */
7702 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7703 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7704
7705 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7706 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7707 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7708 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7709 { }
7710};
7711
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08007712
7713static struct hda_verb alc885_mba21_init_verbs[] = {
7714 /*Internal and HP Speaker Mixer*/
7715 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7716 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7717 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7718 /*Internal Speaker Pin (0x0c)*/
7719 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
7720 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7721 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7722 /* HP Pin: output 0 (0x0e) */
7723 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
7724 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7725 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7726 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
7727 /* Line in (is hp when jack connected)*/
7728 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
7729 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7730
7731 { }
7732 };
7733
7734
Takashi Iwai87350ad2007-08-16 18:19:38 +02007735/* Macbook Pro rev3 */
7736static struct hda_verb alc885_mbp3_init_verbs[] = {
7737 /* Front mixer: unmute input/output amp left and right (volume = 0) */
7738 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7739 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7740 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7741 /* Rear mixer */
7742 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7743 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7744 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007745 /* HP mixer */
7746 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7747 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7748 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai87350ad2007-08-16 18:19:38 +02007749 /* Front Pin: output 0 (0x0c) */
7750 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7751 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7752 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007753 /* HP Pin: output 0 (0x0e) */
Takashi Iwai87350ad2007-08-16 18:19:38 +02007754 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007755 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7756 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai87350ad2007-08-16 18:19:38 +02007757 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7758 /* Mic (rear) pin: input vref at 80% */
7759 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7760 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7761 /* Front Mic pin: input vref at 80% */
7762 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7763 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7764 /* Line In pin: use output 1 when in LineOut mode */
7765 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7766 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7767 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
7768
7769 /* FIXME: use matrix-type input source selection */
7770 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7771 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7772 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7773 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7774 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7775 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7776 /* Input mixer2 */
7777 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7778 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7779 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7780 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7781 /* Input mixer3 */
7782 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7783 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7784 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7785 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7786 /* ADC1: mute amp left and right */
7787 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7788 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7789 /* ADC2: mute amp left and right */
7790 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7791 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7792 /* ADC3: mute amp left and right */
7793 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7794 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7795
7796 { }
7797};
7798
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08007799/* iMac 9,1 */
7800static struct hda_verb alc885_imac91_init_verbs[] = {
7801 /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
7802 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7803 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7804 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7805 /* Rear mixer */
7806 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7807 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7808 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7809 /* HP Pin: output 0 (0x0c) */
7810 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7811 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7812 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7813 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7814 /* Internal Speakers: output 0 (0x0d) */
7815 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7816 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7817 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7818 /* Mic (rear) pin: input vref at 80% */
7819 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7820 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7821 /* Front Mic pin: input vref at 80% */
7822 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7823 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7824 /* Line In pin: use output 1 when in LineOut mode */
7825 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7826 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7827 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
7828
7829 /* FIXME: use matrix-type input source selection */
7830 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7831 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7832 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7833 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7834 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7835 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7836 /* Input mixer2 */
7837 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7838 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7839 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7840 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7841 /* Input mixer3 */
7842 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7843 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7844 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7845 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7846 /* ADC1: mute amp left and right */
7847 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7848 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7849 /* ADC2: mute amp left and right */
7850 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7851 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7852 /* ADC3: mute amp left and right */
7853 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7854 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
7855
7856 { }
7857};
7858
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007859/* iMac 24 mixer. */
7860static struct snd_kcontrol_new alc885_imac24_mixer[] = {
7861 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7862 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
7863 { } /* end */
7864};
7865
7866/* iMac 24 init verbs. */
7867static struct hda_verb alc885_imac24_init_verbs[] = {
7868 /* Internal speakers: output 0 (0x0c) */
7869 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7870 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7871 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7872 /* Internal speakers: output 0 (0x0c) */
7873 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7874 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7875 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
7876 /* Headphone: output 0 (0x0c) */
7877 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7878 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7879 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7880 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
7881 /* Front Mic: input vref at 80% */
7882 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7883 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7884 { }
7885};
7886
7887/* Toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02007888static void alc885_imac24_setup(struct hda_codec *codec)
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007889{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007890 struct alc_spec *spec = codec->spec;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007891
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007892 spec->autocfg.hp_pins[0] = 0x14;
7893 spec->autocfg.speaker_pins[0] = 0x18;
7894 spec->autocfg.speaker_pins[1] = 0x1a;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007895}
7896
Takashi Iwai9d54f082010-02-22 08:34:40 +01007897#define alc885_mb5_setup alc885_imac24_setup
7898#define alc885_macmini3_setup alc885_imac24_setup
7899
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08007900/* Macbook Air 2,1 */
7901static void alc885_mba21_setup(struct hda_codec *codec)
7902{
7903 struct alc_spec *spec = codec->spec;
7904
7905 spec->autocfg.hp_pins[0] = 0x14;
7906 spec->autocfg.speaker_pins[0] = 0x18;
7907}
7908
7909
7910
Takashi Iwai4f5d17062009-08-11 18:17:46 +02007911static void alc885_mbp3_setup(struct hda_codec *codec)
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007912{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007913 struct alc_spec *spec = codec->spec;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02007914
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007915 spec->autocfg.hp_pins[0] = 0x15;
7916 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai87350ad2007-08-16 18:19:38 +02007917}
7918
Takashi Iwai9d54f082010-02-22 08:34:40 +01007919static void alc885_imac91_setup(struct hda_codec *codec)
Alex Murraya76221d2010-01-13 23:15:03 +10307920{
Takashi Iwai9d54f082010-02-22 08:34:40 +01007921 struct alc_spec *spec = codec->spec;
Alex Murraya76221d2010-01-13 23:15:03 +10307922
Takashi Iwai9d54f082010-02-22 08:34:40 +01007923 spec->autocfg.hp_pins[0] = 0x14;
7924 spec->autocfg.speaker_pins[0] = 0x15;
7925 spec->autocfg.speaker_pins[1] = 0x1a;
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08007926}
Takashi Iwai87350ad2007-08-16 18:19:38 +02007927
Kailang Yang272a5272007-05-14 11:00:38 +02007928static struct hda_verb alc882_targa_verbs[] = {
7929 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7930 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7931
7932 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7933 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02007934
Kailang Yang272a5272007-05-14 11:00:38 +02007935 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
7936 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
7937 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
7938
7939 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yang272a5272007-05-14 11:00:38 +02007940 { } /* end */
7941};
7942
7943/* toggle speaker-output according to the hp-jack state */
7944static void alc882_targa_automute(struct hda_codec *codec)
7945{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007946 struct alc_spec *spec = codec->spec;
7947 alc_automute_amp(codec);
Takashi Iwai82beb8f2007-08-10 17:09:26 +02007948 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007949 spec->jack_present ? 1 : 3);
7950}
7951
Takashi Iwai4f5d17062009-08-11 18:17:46 +02007952static void alc882_targa_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007953{
7954 struct alc_spec *spec = codec->spec;
7955
7956 spec->autocfg.hp_pins[0] = 0x14;
7957 spec->autocfg.speaker_pins[0] = 0x1b;
Kailang Yang272a5272007-05-14 11:00:38 +02007958}
7959
7960static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
7961{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02007962 if ((res >> 26) == ALC880_HP_EVENT)
Kailang Yang272a5272007-05-14 11:00:38 +02007963 alc882_targa_automute(codec);
Kailang Yang272a5272007-05-14 11:00:38 +02007964}
7965
7966static struct hda_verb alc882_asus_a7j_verbs[] = {
7967 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7968 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7969
7970 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7971 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7972 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02007973
Kailang Yang272a5272007-05-14 11:00:38 +02007974 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
7975 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
7976 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
7977
7978 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
7979 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
7980 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
7981 { } /* end */
7982};
7983
Takashi Iwai914759b2007-09-06 14:52:04 +02007984static struct hda_verb alc882_asus_a7m_verbs[] = {
7985 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7986 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7987
7988 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7989 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7990 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02007991
Takashi Iwai914759b2007-09-06 14:52:04 +02007992 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
7993 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
7994 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
7995
7996 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
7997 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
7998 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
7999 { } /* end */
8000};
8001
Tobin Davis9102cd12006-12-15 10:02:12 +01008002static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
8003{
8004 unsigned int gpiostate, gpiomask, gpiodir;
8005
8006 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
8007 AC_VERB_GET_GPIO_DATA, 0);
8008
8009 if (!muted)
8010 gpiostate |= (1 << pin);
8011 else
8012 gpiostate &= ~(1 << pin);
8013
8014 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
8015 AC_VERB_GET_GPIO_MASK, 0);
8016 gpiomask |= (1 << pin);
8017
8018 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
8019 AC_VERB_GET_GPIO_DIRECTION, 0);
8020 gpiodir |= (1 << pin);
8021
8022
8023 snd_hda_codec_write(codec, codec->afg, 0,
8024 AC_VERB_SET_GPIO_MASK, gpiomask);
8025 snd_hda_codec_write(codec, codec->afg, 0,
8026 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
8027
8028 msleep(1);
8029
8030 snd_hda_codec_write(codec, codec->afg, 0,
8031 AC_VERB_SET_GPIO_DATA, gpiostate);
8032}
8033
Takashi Iwai7debbe52007-08-16 15:01:03 +02008034/* set up GPIO at initialization */
8035static void alc885_macpro_init_hook(struct hda_codec *codec)
8036{
8037 alc882_gpio_mute(codec, 0, 0);
8038 alc882_gpio_mute(codec, 1, 0);
8039}
8040
8041/* set up GPIO and update auto-muting at initialization */
8042static void alc885_imac24_init_hook(struct hda_codec *codec)
8043{
8044 alc885_macpro_init_hook(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008045 alc_automute_amp(codec);
Takashi Iwai7debbe52007-08-16 15:01:03 +02008046}
8047
Kailang Yangdf694da2005-12-05 19:42:22 +01008048/*
8049 * generic initialization of ADC, input mixers and output mixers
8050 */
Takashi Iwai49535502009-06-30 15:28:30 +02008051static struct hda_verb alc883_auto_init_verbs[] = {
Kailang Yangdf694da2005-12-05 19:42:22 +01008052 /*
8053 * Unmute ADC0-2 and set the default input to mic-in
8054 */
Kailang Yangdf694da2005-12-05 19:42:22 +01008055 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8056 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8057 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8058 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8059
Kailang Yangdf694da2005-12-05 19:42:22 +01008060 /*
8061 * Set up output mixers (0x0c - 0x0f)
8062 */
8063 /* set vol=0 to output mixers */
8064 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8065 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8066 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8067 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8068 /* set up input amps for analog loopback */
8069 /* Amp Indices: DAC = 0, mixer = 1 */
8070 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8071 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8072 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8073 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8074 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8075 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8076 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8077 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8078 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8079 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8080
8081 /* FIXME: use matrix-type input source selection */
8082 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
Kailang Yangdf694da2005-12-05 19:42:22 +01008083 /* Input mixer2 */
Kailang Yang88102f32010-02-04 14:12:58 +01008084 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangdf694da2005-12-05 19:42:22 +01008085 /* Input mixer3 */
Kailang Yang88102f32010-02-04 14:12:58 +01008086 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangdf694da2005-12-05 19:42:22 +01008087 { }
8088};
8089
Torben Schulzeb4c41d2009-05-18 15:02:35 +02008090/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
8091static struct hda_verb alc889A_mb31_ch2_init[] = {
8092 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
8093 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8094 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
8095 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
8096 { } /* end */
8097};
8098
8099/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
8100static struct hda_verb alc889A_mb31_ch4_init[] = {
8101 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
8102 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8103 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
8104 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
8105 { } /* end */
8106};
8107
8108/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
8109static struct hda_verb alc889A_mb31_ch5_init[] = {
8110 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */
8111 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8112 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
8113 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
8114 { } /* end */
8115};
8116
8117/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
8118static struct hda_verb alc889A_mb31_ch6_init[] = {
8119 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */
8120 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */
8121 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
8122 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
8123 { } /* end */
8124};
8125
8126static struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
8127 { 2, alc889A_mb31_ch2_init },
8128 { 4, alc889A_mb31_ch4_init },
8129 { 5, alc889A_mb31_ch5_init },
8130 { 6, alc889A_mb31_ch6_init },
8131};
8132
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01008133static struct hda_verb alc883_medion_eapd_verbs[] = {
8134 /* eanable EAPD on medion laptop */
8135 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
8136 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
8137 { }
8138};
8139
Takashi Iwai49535502009-06-30 15:28:30 +02008140#define alc883_base_mixer alc882_base_mixer
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008141
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008142static struct snd_kcontrol_new alc883_mitac_mixer[] = {
8143 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8144 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8145 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8146 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8147 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8148 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8149 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8150 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8151 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8152 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8153 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8154 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8155 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008156 { } /* end */
8157};
8158
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008159static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
Jiang zhe368c7a92008-03-04 11:20:33 +01008160 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8161 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
8162 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8163 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
8164 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8165 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8166 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8167 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8168 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8169 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Jiang zhe368c7a92008-03-04 11:20:33 +01008170 { } /* end */
8171};
8172
Jiang zhefb97dc62008-03-06 11:07:11 +01008173static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
8174 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8175 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
8176 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8177 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
8178 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8179 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8180 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8181 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8182 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8183 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Jiang zhefb97dc62008-03-06 11:07:11 +01008184 { } /* end */
8185};
8186
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008187static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
8188 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8189 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8190 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8191 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8192 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8193 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8194 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8195 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008196 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008197 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8198 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008199 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008200 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008201 { } /* end */
8202};
8203
8204static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
8205 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8206 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8207 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8208 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8209 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8210 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8211 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8212 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8213 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8214 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8215 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8216 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8217 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8218 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008219 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008220 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8221 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008222 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008223 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008224 { } /* end */
8225};
8226
Jiang zhe17bba1b2008-06-04 12:11:07 +02008227static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
8228 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8229 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8230 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8231 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8232 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
8233 HDA_OUTPUT),
8234 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8235 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8236 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8237 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8238 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8239 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8240 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8241 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8242 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8243 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
8244 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8245 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8246 HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
8247 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Jiang zhe17bba1b2008-06-04 12:11:07 +02008248 { } /* end */
8249};
8250
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02008251static struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
8252 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8253 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8254 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8255 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8256 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
8257 HDA_OUTPUT),
8258 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8259 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8260 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8261 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8262 HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
8263 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8264 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8265 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8266 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
8267 HDA_CODEC_VOLUME("Mic Boost", 0x1b, 0, HDA_INPUT),
8268 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
8269 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8270 HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
8271 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8272 { } /* end */
8273};
8274
Takashi Iwaid1d985f2006-11-23 19:27:12 +01008275static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
Tobin Davisc07584c2006-10-13 12:32:16 +02008276 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008277 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008278 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008279 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008280 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8281 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008282 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8283 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008284 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8285 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8286 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8287 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8288 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8289 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008290 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008291 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8292 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008293 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008294 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008295 { } /* end */
8296};
8297
Sasha Alexandrc2592492009-06-16 14:52:54 -04008298static struct snd_kcontrol_new alc883_targa_mixer[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02008299 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008300 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008301 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008302 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008303 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8304 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8305 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8306 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8307 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8308 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8309 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8310 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8311 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8312 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8313 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008314 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008315 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008316 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008317};
Kailang Yangccc656c2006-10-17 12:32:26 +02008318
Sasha Alexandrc2592492009-06-16 14:52:54 -04008319static struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02008320 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008321 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008322 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008323 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008324 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8325 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8326 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008327 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008328 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Jiang zhe4383fae2008-04-14 12:58:57 +02008329 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8330 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8331 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008332 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008333};
Kailang Yangccc656c2006-10-17 12:32:26 +02008334
Takashi Iwaib99dba32009-09-17 18:23:00 +02008335static struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
8336 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8337 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
8338 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8339 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8340 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8341 { } /* end */
8342};
8343
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008344static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
8345 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8346 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +01008347 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8348 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008349 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8350 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8351 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8352 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008353 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008354};
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008355
Kailang Yang272a5272007-05-14 11:00:38 +02008356static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
8357 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8358 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
8359 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8360 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8361 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8362 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8363 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8364 HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8365 HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02008366 { } /* end */
8367};
8368
8369static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
8370 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8371 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8372 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8373 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8374 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8375 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8376 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8377 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8378 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02008379 { } /* end */
Kailang Yangea1fb292008-08-26 12:58:38 +02008380};
Kailang Yang272a5272007-05-14 11:00:38 +02008381
Tobin Davis2880a862007-08-07 11:50:26 +02008382static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
Kailang Yangd1a991a2007-08-15 16:21:59 +02008383 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8384 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008385 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008386 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8387 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Kailang Yangd1a991a2007-08-15 16:21:59 +02008388 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8389 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8390 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008391 { } /* end */
Kailang Yangd1a991a2007-08-15 16:21:59 +02008392};
Tobin Davis2880a862007-08-07 11:50:26 +02008393
Tony Vroond2fd4b02009-06-21 00:40:10 +01008394static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
8395 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8396 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8397 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8398 HDA_BIND_MUTE("LFE Playback Switch", 0x0f, 2, HDA_INPUT),
Tony Vroon684a8842009-06-26 09:27:50 +01008399 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8400 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Tony Vroond2fd4b02009-06-21 00:40:10 +01008401 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8402 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8403 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8404 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8405 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8406 { } /* end */
8407};
8408
Kailang Yange2757d52008-08-26 13:17:46 +02008409static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
8410 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8411 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8412 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
8413 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
8414 HDA_CODEC_VOLUME_MONO("Center Playback Volume",
8415 0x0d, 1, 0x0, HDA_OUTPUT),
8416 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
8417 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
8418 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
8419 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8420 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Kailang Yange2757d52008-08-26 13:17:46 +02008421 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8422 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8423 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8424 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8425 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8426 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8427 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8428 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8429 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8430 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yange2757d52008-08-26 13:17:46 +02008431 { } /* end */
8432};
8433
Torben Schulzeb4c41d2009-05-18 15:02:35 +02008434static struct snd_kcontrol_new alc889A_mb31_mixer[] = {
8435 /* Output mixers */
8436 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8437 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
8438 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8439 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
8440 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
8441 HDA_OUTPUT),
8442 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
8443 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
8444 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
8445 /* Output switches */
8446 HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
8447 HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
8448 HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
8449 /* Boost mixers */
8450 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
8451 HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
8452 /* Input mixers */
8453 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
8454 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
8455 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8456 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8457 { } /* end */
8458};
8459
Guido Günther3e1647c2009-06-05 00:47:26 +02008460static struct snd_kcontrol_new alc883_vaiott_mixer[] = {
8461 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8462 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8463 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8464 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8465 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
8466 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8467 { } /* end */
8468};
8469
Kailang Yange2757d52008-08-26 13:17:46 +02008470static struct hda_bind_ctls alc883_bind_cap_vol = {
8471 .ops = &snd_hda_bind_vol,
8472 .values = {
8473 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
8474 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
8475 0
8476 },
8477};
8478
8479static struct hda_bind_ctls alc883_bind_cap_switch = {
8480 .ops = &snd_hda_bind_sw,
8481 .values = {
8482 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
8483 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
8484 0
8485 },
8486};
8487
8488static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
8489 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8490 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8491 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8492 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8493 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8494 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8495 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8496 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaif9e336f2008-10-31 16:37:07 +01008497 { } /* end */
8498};
8499
8500static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
Kailang Yange2757d52008-08-26 13:17:46 +02008501 HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
8502 HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
8503 {
8504 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8505 /* .name = "Capture Source", */
8506 .name = "Input Source",
8507 .count = 1,
Takashi Iwai54cbc9a2008-10-31 15:24:04 +01008508 .info = alc_mux_enum_info,
8509 .get = alc_mux_enum_get,
8510 .put = alc_mux_enum_put,
Kailang Yange2757d52008-08-26 13:17:46 +02008511 },
8512 { } /* end */
8513};
8514
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008515static struct snd_kcontrol_new alc883_chmode_mixer[] = {
8516 {
8517 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8518 .name = "Channel Mode",
8519 .info = alc_ch_mode_info,
8520 .get = alc_ch_mode_get,
8521 .put = alc_ch_mode_put,
8522 },
8523 { } /* end */
8524};
8525
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008526/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008527static void alc883_mitac_setup(struct hda_codec *codec)
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008528{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008529 struct alc_spec *spec = codec->spec;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008530
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008531 spec->autocfg.hp_pins[0] = 0x15;
8532 spec->autocfg.speaker_pins[0] = 0x14;
8533 spec->autocfg.speaker_pins[1] = 0x17;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008534}
8535
8536/* auto-toggle front mic */
8537/*
8538static void alc883_mitac_mic_automute(struct hda_codec *codec)
8539{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008540 unsigned char bits = snd_hda_jack_detect(codec, 0x18) ? HDA_AMP_MUTE : 0;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008541
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008542 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
8543}
8544*/
8545
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008546static struct hda_verb alc883_mitac_verbs[] = {
8547 /* HP */
8548 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8549 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8550 /* Subwoofer */
8551 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
8552 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8553
8554 /* enable unsolicited event */
8555 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8556 /* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, */
8557
8558 { } /* end */
8559};
8560
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04308561static struct hda_verb alc883_clevo_m540r_verbs[] = {
8562 /* HP */
8563 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8564 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8565 /* Int speaker */
8566 /*{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},*/
8567
8568 /* enable unsolicited event */
8569 /*
8570 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8571 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
8572 */
8573
8574 { } /* end */
8575};
8576
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008577static struct hda_verb alc883_clevo_m720_verbs[] = {
Jiang zhe368c7a92008-03-04 11:20:33 +01008578 /* HP */
8579 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8580 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8581 /* Int speaker */
8582 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
8583 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8584
8585 /* enable unsolicited event */
8586 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008587 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
Jiang zhe368c7a92008-03-04 11:20:33 +01008588
8589 { } /* end */
8590};
8591
Jiang zhefb97dc62008-03-06 11:07:11 +01008592static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
8593 /* HP */
8594 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8595 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8596 /* Subwoofer */
8597 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
8598 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8599
8600 /* enable unsolicited event */
8601 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8602
8603 { } /* end */
8604};
8605
Sasha Alexandrc2592492009-06-16 14:52:54 -04008606static struct hda_verb alc883_targa_verbs[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02008607 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8608 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8609
8610 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8611 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02008612
David Heidelberger64a8be72009-06-08 16:15:18 +02008613/* Connect Line-Out side jack (SPDIF) to Side */
8614 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8615 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8616 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
8617/* Connect Mic jack to CLFE */
8618 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8619 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8620 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
8621/* Connect Line-in jack to Surround */
8622 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8623 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8624 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
8625/* Connect HP out jack to Front */
8626 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8627 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8628 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangccc656c2006-10-17 12:32:26 +02008629
8630 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yangccc656c2006-10-17 12:32:26 +02008631
8632 { } /* end */
8633};
8634
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008635static struct hda_verb alc883_lenovo_101e_verbs[] = {
8636 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8637 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
8638 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
8639 { } /* end */
8640};
8641
Kailang Yang272a5272007-05-14 11:00:38 +02008642static struct hda_verb alc883_lenovo_nb0763_verbs[] = {
8643 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8644 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8645 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8646 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8647 { } /* end */
8648};
8649
8650static struct hda_verb alc888_lenovo_ms7195_verbs[] = {
8651 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8652 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8653 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8654 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},
8655 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8656 { } /* end */
8657};
8658
Kailang Yang189609a2007-08-20 11:31:23 +02008659static struct hda_verb alc883_haier_w66_verbs[] = {
8660 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8661 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8662
8663 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8664
8665 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
8666 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8667 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8668 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8669 { } /* end */
8670};
8671
Kailang Yange2757d52008-08-26 13:17:46 +02008672static struct hda_verb alc888_lenovo_sky_verbs[] = {
8673 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8674 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8675 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8676 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8677 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8678 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8679 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8680 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8681 { } /* end */
8682};
8683
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008684static struct hda_verb alc888_6st_dell_verbs[] = {
8685 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8686 { }
8687};
8688
Guido Günther3e1647c2009-06-05 00:47:26 +02008689static struct hda_verb alc883_vaiott_verbs[] = {
8690 /* HP */
8691 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8692 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8693
8694 /* enable unsolicited event */
8695 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8696
8697 { } /* end */
8698};
8699
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008700static void alc888_3st_hp_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008701{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008702 struct alc_spec *spec = codec->spec;
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008703
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008704 spec->autocfg.hp_pins[0] = 0x1b;
8705 spec->autocfg.speaker_pins[0] = 0x14;
8706 spec->autocfg.speaker_pins[1] = 0x16;
8707 spec->autocfg.speaker_pins[2] = 0x18;
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008708}
8709
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008710static struct hda_verb alc888_3st_hp_verbs[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008711 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
Herton Ronaldo Krzesinskif32a19e2008-03-18 09:27:08 +01008712 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
8713 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01008714 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03008715 { } /* end */
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01008716};
8717
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008718/*
8719 * 2ch mode
8720 */
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008721static struct hda_verb alc888_3st_hp_2ch_init[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008722 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8723 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8724 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
8725 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008726 { } /* end */
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008727};
8728
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008729/*
8730 * 4ch mode
8731 */
8732static struct hda_verb alc888_3st_hp_4ch_init[] = {
8733 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
8734 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
8735 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8736 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
8737 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
8738 { } /* end */
8739};
8740
8741/*
8742 * 6ch mode
8743 */
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008744static struct hda_verb alc888_3st_hp_6ch_init[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008745 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8746 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008747 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008748 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8749 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008750 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
8751 { } /* end */
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008752};
8753
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008754static struct hda_channel_mode alc888_3st_hp_modes[3] = {
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008755 { 2, alc888_3st_hp_2ch_init },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03008756 { 4, alc888_3st_hp_4ch_init },
Claudio Matsuoka4723c022007-07-13 14:36:19 +02008757 { 6, alc888_3st_hp_6ch_init },
Claudio Matsuoka8341de62007-07-06 12:10:45 +02008758};
8759
Kailang Yang272a5272007-05-14 11:00:38 +02008760/* toggle front-jack and RCA according to the hp-jack state */
8761static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
8762{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008763 unsigned int present = snd_hda_jack_detect(codec, 0x1b);
Kailang Yangea1fb292008-08-26 12:58:38 +02008764
Takashi Iwai47fd8302007-08-10 17:11:07 +02008765 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
8766 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
8767 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8768 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
Kailang Yang272a5272007-05-14 11:00:38 +02008769}
8770
8771/* toggle RCA according to the front-jack state */
8772static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
8773{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008774 unsigned int present = snd_hda_jack_detect(codec, 0x14);
Kailang Yangea1fb292008-08-26 12:58:38 +02008775
Takashi Iwai47fd8302007-08-10 17:11:07 +02008776 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8777 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
Kailang Yang272a5272007-05-14 11:00:38 +02008778}
Takashi Iwai47fd8302007-08-10 17:11:07 +02008779
Kailang Yang272a5272007-05-14 11:00:38 +02008780static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
8781 unsigned int res)
8782{
8783 if ((res >> 26) == ALC880_HP_EVENT)
8784 alc888_lenovo_ms7195_front_automute(codec);
8785 if ((res >> 26) == ALC880_FRONT_EVENT)
8786 alc888_lenovo_ms7195_rca_automute(codec);
8787}
8788
8789static struct hda_verb alc883_medion_md2_verbs[] = {
8790 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8791 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8792
8793 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8794
8795 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8796 { } /* end */
8797};
8798
8799/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008800static void alc883_medion_md2_setup(struct hda_codec *codec)
Kailang Yang272a5272007-05-14 11:00:38 +02008801{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008802 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02008803
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008804 spec->autocfg.hp_pins[0] = 0x14;
8805 spec->autocfg.speaker_pins[0] = 0x15;
Kailang Yang272a5272007-05-14 11:00:38 +02008806}
8807
Kailang Yangccc656c2006-10-17 12:32:26 +02008808/* toggle speaker-output according to the hp-jack state */
Sasha Alexandrc2592492009-06-16 14:52:54 -04008809#define alc883_targa_init_hook alc882_targa_init_hook
8810#define alc883_targa_unsol_event alc882_targa_unsol_event
Jiang zhe368c7a92008-03-04 11:20:33 +01008811
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008812static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
8813{
8814 unsigned int present;
8815
Takashi Iwaid56757a2009-11-18 08:00:14 +01008816 present = snd_hda_jack_detect(codec, 0x18);
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008817 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
8818 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
8819}
8820
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008821static void alc883_clevo_m720_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008822{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008823 struct alc_spec *spec = codec->spec;
8824
8825 spec->autocfg.hp_pins[0] = 0x15;
8826 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008827}
8828
8829static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
8830{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008831 alc_automute_amp(codec);
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008832 alc883_clevo_m720_mic_automute(codec);
8833}
8834
8835static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
Jiang zhe368c7a92008-03-04 11:20:33 +01008836 unsigned int res)
8837{
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008838 switch (res >> 26) {
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008839 case ALC880_MIC_EVENT:
8840 alc883_clevo_m720_mic_automute(codec);
8841 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008842 default:
8843 alc_automute_amp_unsol_event(codec, res);
8844 break;
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008845 }
Jiang zhe368c7a92008-03-04 11:20:33 +01008846}
8847
Jiang zhefb97dc62008-03-06 11:07:11 +01008848/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008849static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
Jiang zhefb97dc62008-03-06 11:07:11 +01008850{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008851 struct alc_spec *spec = codec->spec;
Jiang zhefb97dc62008-03-06 11:07:11 +01008852
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008853 spec->autocfg.hp_pins[0] = 0x14;
8854 spec->autocfg.speaker_pins[0] = 0x15;
Jiang zhefb97dc62008-03-06 11:07:11 +01008855}
8856
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008857static void alc883_haier_w66_setup(struct hda_codec *codec)
Jiang zhefb97dc62008-03-06 11:07:11 +01008858{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008859 struct alc_spec *spec = codec->spec;
Jiang zhefb97dc62008-03-06 11:07:11 +01008860
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008861 spec->autocfg.hp_pins[0] = 0x1b;
8862 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang189609a2007-08-20 11:31:23 +02008863}
8864
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008865static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
8866{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008867 int bits = snd_hda_jack_detect(codec, 0x14) ? HDA_AMP_MUTE : 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008868
Takashi Iwai47fd8302007-08-10 17:11:07 +02008869 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8870 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008871}
8872
8873static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
8874{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008875 int bits = snd_hda_jack_detect(codec, 0x1b) ? HDA_AMP_MUTE : 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008876
Takashi Iwai47fd8302007-08-10 17:11:07 +02008877 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
8878 HDA_AMP_MUTE, bits);
8879 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
8880 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008881}
8882
8883static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
8884 unsigned int res)
8885{
8886 if ((res >> 26) == ALC880_HP_EVENT)
8887 alc883_lenovo_101e_all_automute(codec);
8888 if ((res >> 26) == ALC880_FRONT_EVENT)
8889 alc883_lenovo_101e_ispeaker_automute(codec);
8890}
8891
Takashi Iwai676a9b52007-08-16 15:23:35 +02008892/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008893static void alc883_acer_aspire_setup(struct hda_codec *codec)
Takashi Iwai676a9b52007-08-16 15:23:35 +02008894{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008895 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02008896
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008897 spec->autocfg.hp_pins[0] = 0x14;
8898 spec->autocfg.speaker_pins[0] = 0x15;
8899 spec->autocfg.speaker_pins[1] = 0x16;
Takashi Iwai676a9b52007-08-16 15:23:35 +02008900}
8901
Kailang Yangd1a991a2007-08-15 16:21:59 +02008902static struct hda_verb alc883_acer_eapd_verbs[] = {
8903 /* HP Pin: output 0 (0x0c) */
8904 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8905 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8906 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8907 /* Front Pin: output 0 (0x0c) */
Takashi Iwai676a9b52007-08-16 15:23:35 +02008908 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8909 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangd1a991a2007-08-15 16:21:59 +02008910 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangd1a991a2007-08-15 16:21:59 +02008911 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
8912 /* eanable EAPD on medion laptop */
8913 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
8914 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
Takashi Iwai676a9b52007-08-16 15:23:35 +02008915 /* enable unsolicited event */
8916 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yangd1a991a2007-08-15 16:21:59 +02008917 { }
8918};
8919
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02008920static struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
8921 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8922 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
8923 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8924 { } /* end */
8925};
8926
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008927static void alc888_6st_dell_setup(struct hda_codec *codec)
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01008928{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008929 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02008930
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008931 spec->autocfg.hp_pins[0] = 0x1b;
8932 spec->autocfg.speaker_pins[0] = 0x14;
8933 spec->autocfg.speaker_pins[1] = 0x15;
8934 spec->autocfg.speaker_pins[2] = 0x16;
8935 spec->autocfg.speaker_pins[3] = 0x17;
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01008936}
8937
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008938static void alc888_lenovo_sky_setup(struct hda_codec *codec)
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01008939{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008940 struct alc_spec *spec = codec->spec;
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01008941
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008942 spec->autocfg.hp_pins[0] = 0x1b;
8943 spec->autocfg.speaker_pins[0] = 0x14;
8944 spec->autocfg.speaker_pins[1] = 0x15;
8945 spec->autocfg.speaker_pins[2] = 0x16;
8946 spec->autocfg.speaker_pins[3] = 0x17;
8947 spec->autocfg.speaker_pins[4] = 0x1a;
Kailang Yange2757d52008-08-26 13:17:46 +02008948}
8949
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008950static void alc883_vaiott_setup(struct hda_codec *codec)
Guido Günther3e1647c2009-06-05 00:47:26 +02008951{
8952 struct alc_spec *spec = codec->spec;
8953
8954 spec->autocfg.hp_pins[0] = 0x15;
8955 spec->autocfg.speaker_pins[0] = 0x14;
8956 spec->autocfg.speaker_pins[1] = 0x17;
Guido Günther3e1647c2009-06-05 00:47:26 +02008957}
8958
Kailang Yange2757d52008-08-26 13:17:46 +02008959static struct hda_verb alc888_asus_m90v_verbs[] = {
8960 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8961 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8962 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8963 /* enable unsolicited event */
8964 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8965 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
8966 { } /* end */
8967};
8968
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008969static void alc883_mode2_setup(struct hda_codec *codec)
Kailang Yange2757d52008-08-26 13:17:46 +02008970{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008971 struct alc_spec *spec = codec->spec;
Kailang Yange2757d52008-08-26 13:17:46 +02008972
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008973 spec->autocfg.hp_pins[0] = 0x1b;
8974 spec->autocfg.speaker_pins[0] = 0x14;
8975 spec->autocfg.speaker_pins[1] = 0x15;
8976 spec->autocfg.speaker_pins[2] = 0x16;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008977 spec->ext_mic.pin = 0x18;
8978 spec->int_mic.pin = 0x19;
8979 spec->ext_mic.mux_idx = 0;
8980 spec->int_mic.mux_idx = 1;
8981 spec->auto_mic = 1;
Kailang Yange2757d52008-08-26 13:17:46 +02008982}
8983
8984static struct hda_verb alc888_asus_eee1601_verbs[] = {
8985 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8986 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8987 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8988 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8989 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8990 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
8991 {0x20, AC_VERB_SET_PROC_COEF, 0x0838},
8992 /* enable unsolicited event */
8993 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8994 { } /* end */
8995};
8996
Kailang Yange2757d52008-08-26 13:17:46 +02008997static void alc883_eee1601_inithook(struct hda_codec *codec)
8998{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008999 struct alc_spec *spec = codec->spec;
9000
9001 spec->autocfg.hp_pins[0] = 0x14;
9002 spec->autocfg.speaker_pins[0] = 0x1b;
9003 alc_automute_pin(codec);
Kailang Yange2757d52008-08-26 13:17:46 +02009004}
9005
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009006static struct hda_verb alc889A_mb31_verbs[] = {
9007 /* Init rear pin (used as headphone output) */
9008 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */
9009 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */
9010 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9011 /* Init line pin (used as output in 4ch and 6ch mode) */
9012 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */
9013 /* Init line 2 pin (used as headphone out by default) */
9014 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */
9015 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
9016 { } /* end */
9017};
9018
9019/* Mute speakers according to the headphone jack state */
9020static void alc889A_mb31_automute(struct hda_codec *codec)
9021{
9022 unsigned int present;
9023
9024 /* Mute only in 2ch or 4ch mode */
9025 if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
9026 == 0x00) {
Wu Fengguang864f92b2009-11-18 12:38:02 +08009027 present = snd_hda_jack_detect(codec, 0x15);
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009028 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9029 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9030 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
9031 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9032 }
9033}
9034
9035static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
9036{
9037 if ((res >> 26) == ALC880_HP_EVENT)
9038 alc889A_mb31_automute(codec);
9039}
9040
Takashi Iwai49535502009-06-30 15:28:30 +02009041
Takashi Iwaicb53c622007-08-10 17:21:45 +02009042#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwai49535502009-06-30 15:28:30 +02009043#define alc882_loopbacks alc880_loopbacks
Takashi Iwaicb53c622007-08-10 17:21:45 +02009044#endif
9045
Sasha Alexandrdef319f2009-06-16 16:00:15 -04009046/* pcm configuration: identical with ALC880 */
Takashi Iwai49535502009-06-30 15:28:30 +02009047#define alc882_pcm_analog_playback alc880_pcm_analog_playback
9048#define alc882_pcm_analog_capture alc880_pcm_analog_capture
9049#define alc882_pcm_digital_playback alc880_pcm_digital_playback
9050#define alc882_pcm_digital_capture alc880_pcm_digital_capture
9051
9052static hda_nid_t alc883_slave_dig_outs[] = {
9053 ALC1200_DIGOUT_NID, 0,
9054};
9055
9056static hda_nid_t alc1200_slave_dig_outs[] = {
9057 ALC883_DIGOUT_NID, 0,
9058};
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009059
9060/*
9061 * configuration and preset
9062 */
Takashi Iwai49535502009-06-30 15:28:30 +02009063static const char *alc882_models[ALC882_MODEL_LAST] = {
9064 [ALC882_3ST_DIG] = "3stack-dig",
9065 [ALC882_6ST_DIG] = "6stack-dig",
9066 [ALC882_ARIMA] = "arima",
9067 [ALC882_W2JC] = "w2jc",
9068 [ALC882_TARGA] = "targa",
9069 [ALC882_ASUS_A7J] = "asus-a7j",
9070 [ALC882_ASUS_A7M] = "asus-a7m",
9071 [ALC885_MACPRO] = "macpro",
9072 [ALC885_MB5] = "mb5",
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009073 [ALC885_MACMINI3] = "macmini3",
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08009074 [ALC885_MBA21] = "mba21",
Takashi Iwai49535502009-06-30 15:28:30 +02009075 [ALC885_MBP3] = "mbp3",
9076 [ALC885_IMAC24] = "imac24",
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009077 [ALC885_IMAC91] = "imac91",
Takashi Iwai49535502009-06-30 15:28:30 +02009078 [ALC883_3ST_2ch_DIG] = "3stack-2ch-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009079 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
9080 [ALC883_3ST_6ch] = "3stack-6ch",
Takashi Iwai49535502009-06-30 15:28:30 +02009081 [ALC883_6ST_DIG] = "alc883-6stack-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009082 [ALC883_TARGA_DIG] = "targa-dig",
9083 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
David Heidelberger64a8be72009-06-08 16:15:18 +02009084 [ALC883_TARGA_8ch_DIG] = "targa-8ch-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009085 [ALC883_ACER] = "acer",
Tobin Davis2880a862007-08-07 11:50:26 +02009086 [ALC883_ACER_ASPIRE] = "acer-aspire",
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009087 [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g",
Takashi Iwaib1a91462009-06-21 10:56:44 +02009088 [ALC888_ACER_ASPIRE_6530G] = "acer-aspire-6530g",
Hector Martin3b315d72009-06-02 10:54:19 +02009089 [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g",
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009090 [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009091 [ALC883_MEDION] = "medion",
Kailang Yang272a5272007-05-14 11:00:38 +02009092 [ALC883_MEDION_MD2] = "medion-md2",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009093 [ALC883_LAPTOP_EAPD] = "laptop-eapd",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009094 [ALC883_LENOVO_101E_2ch] = "lenovo-101e",
Kailang Yang272a5272007-05-14 11:00:38 +02009095 [ALC883_LENOVO_NB0763] = "lenovo-nb0763",
9096 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
Kailang Yange2757d52008-08-26 13:17:46 +02009097 [ALC888_LENOVO_SKY] = "lenovo-sky",
Kailang Yang189609a2007-08-20 11:31:23 +02009098 [ALC883_HAIER_W66] = "haier-w66",
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009099 [ALC888_3ST_HP] = "3stack-hp",
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009100 [ALC888_6ST_DELL] = "6stack-dell",
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01009101 [ALC883_MITAC] = "mitac",
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04309102 [ALC883_CLEVO_M540R] = "clevo-m540r",
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009103 [ALC883_CLEVO_M720] = "clevo-m720",
Jiang zhefb97dc62008-03-06 11:07:11 +01009104 [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009105 [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
Jiang zhe17bba1b2008-06-04 12:11:07 +02009106 [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009107 [ALC889A_INTEL] = "intel-alc889a",
9108 [ALC889_INTEL] = "intel-x58",
Wu Fengguang3ab90932008-11-17 09:51:09 +01009109 [ALC1200_ASUS_P5Q] = "asus-p5q",
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009110 [ALC889A_MB31] = "mb31",
Guido Günther3e1647c2009-06-05 00:47:26 +02009111 [ALC883_SONY_VAIO_TT] = "sony-vaio-tt",
Takashi Iwai49535502009-06-30 15:28:30 +02009112 [ALC882_AUTO] = "auto",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009113};
9114
Takashi Iwai49535502009-06-30 15:28:30 +02009115static struct snd_pci_quirk alc882_cfg_tbl[] = {
9116 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
9117
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009118 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
Takashi Iwai69e50282008-11-03 10:07:43 +01009119 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
Takashi Iwai9b6682f2009-03-23 22:50:52 +01009120 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009121 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
9122 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
Jaroslav Kysela0b18cb12008-07-28 17:07:07 +02009123 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009124 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
9125 ALC888_ACER_ASPIRE_4930G),
Lukasz Wojnilowicza8e4f9d2009-01-08 12:00:49 +01009126 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
Takashi Iwai83dd7402009-11-24 08:57:53 +01009127 ALC888_ACER_ASPIRE_4930G),
Hector Martin3b315d72009-06-02 10:54:19 +02009128 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
9129 ALC888_ACER_ASPIRE_8930G),
Takashi Iwaie46b0c82009-06-13 10:16:43 +02009130 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
9131 ALC888_ACER_ASPIRE_8930G),
Takashi Iwai49535502009-06-30 15:28:30 +02009132 SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
9133 SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
Lukasz Wojnilowicza8e4f9d2009-01-08 12:00:49 +01009134 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
Takashi Iwaidde65352009-06-25 08:25:35 +02009135 ALC888_ACER_ASPIRE_6530G),
Juan Jesus Garcia de Soriacc374c42009-02-23 08:11:59 +01009136 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
Tony Vroond2fd4b02009-06-21 00:40:10 +01009137 ALC888_ACER_ASPIRE_6530G),
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009138 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
9139 ALC888_ACER_ASPIRE_7730G),
Takashi Iwai22b530e2009-05-13 11:32:52 +02009140 /* default Acer -- disabled as it causes more problems.
9141 * model=auto should work fine now
9142 */
9143 /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
Takashi Iwai49535502009-06-30 15:28:30 +02009144
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009145 SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
Takashi Iwai49535502009-06-30 15:28:30 +02009146
Tobin Davisfebe3372007-06-12 11:27:46 +02009147 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009148 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
9149 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
Herton Ronaldo Krzesinski5d85f8d2008-03-20 12:13:46 +01009150 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
Chris Bagwell06bf3e12009-01-01 10:32:08 +01009151 SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
Herton Ronaldo Krzesinski7ec30f02009-03-04 14:22:52 -03009152 SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
Takashi Iwai49535502009-06-30 15:28:30 +02009153
9154 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
9155 SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
9156 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
Kailang Yanga01c30c2008-10-15 11:14:58 +02009157 SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
Takashi Iwai49535502009-06-30 15:28:30 +02009158 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
9159 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
9160 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009161 SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
Mackenzie Morgan44a678d2009-02-10 17:13:43 +01009162 SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
Wu Fengguang3ab90932008-11-17 09:51:09 +01009163 SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
Kailang Yange2757d52008-08-26 13:17:46 +02009164 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
Takashi Iwai49535502009-06-30 15:28:30 +02009165
9166 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
Travis Place97ec7102008-05-23 18:31:46 +02009167 SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
Takashi Iwai49535502009-06-30 15:28:30 +02009168 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
Luke Yelavich2de686d2009-01-16 15:08:02 +11009169 SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009170 SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
9171 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
Kailang Yange2757d52008-08-26 13:17:46 +02009172 SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009173 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
Takashi Iwai49535502009-06-30 15:28:30 +02009174 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
9175
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009176 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
9177 SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
9178 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
Takashi Iwai49535502009-06-30 15:28:30 +02009179 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
Takashi Iwai2fef62c2009-12-18 08:48:42 +01009180 SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
Takashi Iwai49535502009-06-30 15:28:30 +02009181 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009182 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
Pascal Terjan82808232008-03-04 11:33:28 +01009183 SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009184 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
9185 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
9186 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
9187 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
9188 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
9189 SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
William Westonb1e44222009-07-08 01:10:05 -07009190 SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009191 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
9192 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
9193 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
David Heidelberger64a8be72009-06-08 16:15:18 +02009194 SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009195 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
9196 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
Tobin Davis799f88a2007-05-29 14:29:08 +02009197 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
Takashi Iwaiee095432008-11-25 15:03:38 +01009198 SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
Herton Ronaldo Krzesinski86d34b72008-03-18 09:27:59 +01009199 SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
Leonard Norrgard2a296cb2007-01-08 11:28:22 +01009200 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
Tobin Davis2dcd5222007-07-10 17:04:57 +02009201 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
Sasha Alexandrdf01b8a2009-06-16 14:46:17 -04009202 SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009203 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
William Westonb1e44222009-07-08 01:10:05 -07009204 SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
Takashi Iwai49535502009-06-30 15:28:30 +02009205
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009206 SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009207 SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
9208 SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04309209 SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
Takashi Iwaidea0a502009-02-09 17:14:52 +01009210 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
Daniel T Chene60623b2007-05-29 03:41:55 -04009211 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
Takashi Iwai49535502009-06-30 15:28:30 +02009212 /* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009213 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
Takashi Iwaibfb53032009-04-14 14:51:04 +02009214 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
Takashi Iwaif67d8172009-02-04 23:30:19 +01009215 ALC883_FUJITSU_PI2515),
Takashi Iwaibfb53032009-04-14 14:51:04 +02009216 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009217 ALC888_FUJITSU_XA3530),
Kailang Yang272a5272007-05-14 11:00:38 +02009218 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
Kailang Yang272a5272007-05-14 11:00:38 +02009219 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009220 SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
9221 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
Kailang Yange2757d52008-08-26 13:17:46 +02009222 SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
Kailang Yang272a5272007-05-14 11:00:38 +02009223 SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
Takashi Iwai959973b2008-11-05 11:30:56 +01009224 SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
Andrew Paprocki0b167bf2008-02-03 10:15:44 +01009225 SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
Kailang Yang189609a2007-08-20 11:31:23 +02009226 SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
Takashi Iwai49535502009-06-30 15:28:30 +02009227
Jiang zhe17bba1b2008-06-04 12:11:07 +02009228 SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
9229 SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
Luke Yelavich2de686d2009-01-16 15:08:02 +11009230 SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009231 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
9232 SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
9233 SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009234 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
Takashi Iwai49535502009-06-30 15:28:30 +02009235
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009236 {}
9237};
9238
Takashi Iwai49535502009-06-30 15:28:30 +02009239/* codec SSID table for Intel Mac */
9240static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
9241 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
9242 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
9243 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
9244 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
9245 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
9246 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
9247 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
9248 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
9249 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
9250 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009251 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
Takashi Iwai49535502009-06-30 15:28:30 +02009252 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
Daniel T Chen46ef6ec2009-11-11 14:32:10 -05009253 /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
9254 * so apparently no perfect solution yet
Takashi Iwai49535502009-06-30 15:28:30 +02009255 */
9256 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
Daniel T Chen46ef6ec2009-11-11 14:32:10 -05009257 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009258 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
Takashi Iwai49535502009-06-30 15:28:30 +02009259 {} /* terminator */
Wu Fengguangf3cd3f52009-04-02 19:44:18 +08009260};
9261
Takashi Iwai49535502009-06-30 15:28:30 +02009262static struct alc_config_preset alc882_presets[] = {
9263 [ALC882_3ST_DIG] = {
9264 .mixers = { alc882_base_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009265 .init_verbs = { alc882_base_init_verbs,
9266 alc882_adc1_init_verbs },
Takashi Iwai49535502009-06-30 15:28:30 +02009267 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9268 .dac_nids = alc882_dac_nids,
9269 .dig_out_nid = ALC882_DIGOUT_NID,
9270 .dig_in_nid = ALC882_DIGIN_NID,
9271 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9272 .channel_mode = alc882_ch_modes,
9273 .need_dac_fix = 1,
9274 .input_mux = &alc882_capture_source,
9275 },
9276 [ALC882_6ST_DIG] = {
9277 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009278 .init_verbs = { alc882_base_init_verbs,
9279 alc882_adc1_init_verbs },
Takashi Iwai49535502009-06-30 15:28:30 +02009280 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9281 .dac_nids = alc882_dac_nids,
9282 .dig_out_nid = ALC882_DIGOUT_NID,
9283 .dig_in_nid = ALC882_DIGIN_NID,
9284 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
9285 .channel_mode = alc882_sixstack_modes,
9286 .input_mux = &alc882_capture_source,
9287 },
9288 [ALC882_ARIMA] = {
9289 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009290 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9291 alc882_eapd_verbs },
Takashi Iwai49535502009-06-30 15:28:30 +02009292 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9293 .dac_nids = alc882_dac_nids,
9294 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
9295 .channel_mode = alc882_sixstack_modes,
9296 .input_mux = &alc882_capture_source,
9297 },
9298 [ALC882_W2JC] = {
9299 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009300 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9301 alc882_eapd_verbs, alc880_gpio1_init_verbs },
Takashi Iwai49535502009-06-30 15:28:30 +02009302 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9303 .dac_nids = alc882_dac_nids,
9304 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
9305 .channel_mode = alc880_threestack_modes,
9306 .need_dac_fix = 1,
9307 .input_mux = &alc882_capture_source,
9308 .dig_out_nid = ALC882_DIGOUT_NID,
9309 },
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08009310 [ALC885_MBA21] = {
9311 .mixers = { alc885_mba21_mixer },
9312 .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
9313 .num_dacs = 2,
9314 .dac_nids = alc882_dac_nids,
9315 .channel_mode = alc885_mba21_ch_modes,
9316 .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
9317 .input_mux = &alc882_capture_source,
9318 .unsol_event = alc_automute_amp_unsol_event,
9319 .setup = alc885_mba21_setup,
9320 .init_hook = alc_automute_amp,
9321 },
Takashi Iwai49535502009-06-30 15:28:30 +02009322 [ALC885_MBP3] = {
9323 .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
9324 .init_verbs = { alc885_mbp3_init_verbs,
9325 alc880_gpio1_init_verbs },
Takashi Iwaibe0ae922009-08-31 08:27:10 +02009326 .num_dacs = 2,
Takashi Iwai49535502009-06-30 15:28:30 +02009327 .dac_nids = alc882_dac_nids,
Takashi Iwaibe0ae922009-08-31 08:27:10 +02009328 .hp_nid = 0x04,
9329 .channel_mode = alc885_mbp_4ch_modes,
9330 .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
Takashi Iwai49535502009-06-30 15:28:30 +02009331 .input_mux = &alc882_capture_source,
9332 .dig_out_nid = ALC882_DIGOUT_NID,
9333 .dig_in_nid = ALC882_DIGIN_NID,
9334 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009335 .setup = alc885_mbp3_setup,
9336 .init_hook = alc_automute_amp,
Takashi Iwai49535502009-06-30 15:28:30 +02009337 },
9338 [ALC885_MB5] = {
9339 .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
9340 .init_verbs = { alc885_mb5_init_verbs,
9341 alc880_gpio1_init_verbs },
9342 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9343 .dac_nids = alc882_dac_nids,
9344 .channel_mode = alc885_mb5_6ch_modes,
9345 .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
9346 .input_mux = &mb5_capture_source,
9347 .dig_out_nid = ALC882_DIGOUT_NID,
9348 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009349 .unsol_event = alc_automute_amp_unsol_event,
9350 .setup = alc885_mb5_setup,
9351 .init_hook = alc_automute_amp,
Takashi Iwai49535502009-06-30 15:28:30 +02009352 },
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009353 [ALC885_MACMINI3] = {
9354 .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
9355 .init_verbs = { alc885_macmini3_init_verbs,
9356 alc880_gpio1_init_verbs },
9357 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9358 .dac_nids = alc882_dac_nids,
9359 .channel_mode = alc885_macmini3_6ch_modes,
9360 .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
9361 .input_mux = &macmini3_capture_source,
9362 .dig_out_nid = ALC882_DIGOUT_NID,
9363 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009364 .unsol_event = alc_automute_amp_unsol_event,
9365 .setup = alc885_macmini3_setup,
9366 .init_hook = alc_automute_amp,
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009367 },
Takashi Iwai49535502009-06-30 15:28:30 +02009368 [ALC885_MACPRO] = {
9369 .mixers = { alc882_macpro_mixer },
9370 .init_verbs = { alc882_macpro_init_verbs },
9371 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9372 .dac_nids = alc882_dac_nids,
9373 .dig_out_nid = ALC882_DIGOUT_NID,
9374 .dig_in_nid = ALC882_DIGIN_NID,
9375 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9376 .channel_mode = alc882_ch_modes,
9377 .input_mux = &alc882_capture_source,
9378 .init_hook = alc885_macpro_init_hook,
9379 },
9380 [ALC885_IMAC24] = {
9381 .mixers = { alc885_imac24_mixer },
9382 .init_verbs = { alc885_imac24_init_verbs },
9383 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9384 .dac_nids = alc882_dac_nids,
9385 .dig_out_nid = ALC882_DIGOUT_NID,
9386 .dig_in_nid = ALC882_DIGIN_NID,
9387 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9388 .channel_mode = alc882_ch_modes,
9389 .input_mux = &alc882_capture_source,
9390 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009391 .setup = alc885_imac24_setup,
Takashi Iwai49535502009-06-30 15:28:30 +02009392 .init_hook = alc885_imac24_init_hook,
9393 },
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009394 [ALC885_IMAC91] = {
9395 .mixers = { alc885_imac91_mixer, alc882_chmode_mixer },
9396 .init_verbs = { alc885_imac91_init_verbs,
9397 alc880_gpio1_init_verbs },
9398 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9399 .dac_nids = alc882_dac_nids,
9400 .channel_mode = alc885_mbp_4ch_modes,
9401 .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
9402 .input_mux = &alc882_capture_source,
9403 .dig_out_nid = ALC882_DIGOUT_NID,
9404 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009405 .unsol_event = alc_automute_amp_unsol_event,
9406 .setup = alc885_imac91_setup,
9407 .init_hook = alc_automute_amp,
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009408 },
Takashi Iwai49535502009-06-30 15:28:30 +02009409 [ALC882_TARGA] = {
9410 .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009411 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
Takashi Iwai31909b82009-07-10 12:33:48 +02009412 alc880_gpio3_init_verbs, alc882_targa_verbs},
Takashi Iwai49535502009-06-30 15:28:30 +02009413 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9414 .dac_nids = alc882_dac_nids,
9415 .dig_out_nid = ALC882_DIGOUT_NID,
9416 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
9417 .adc_nids = alc882_adc_nids,
9418 .capsrc_nids = alc882_capsrc_nids,
9419 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
9420 .channel_mode = alc882_3ST_6ch_modes,
9421 .need_dac_fix = 1,
9422 .input_mux = &alc882_capture_source,
9423 .unsol_event = alc882_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009424 .setup = alc882_targa_setup,
9425 .init_hook = alc882_targa_automute,
Takashi Iwai49535502009-06-30 15:28:30 +02009426 },
9427 [ALC882_ASUS_A7J] = {
9428 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009429 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9430 alc882_asus_a7j_verbs},
Takashi Iwai49535502009-06-30 15:28:30 +02009431 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9432 .dac_nids = alc882_dac_nids,
9433 .dig_out_nid = ALC882_DIGOUT_NID,
9434 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
9435 .adc_nids = alc882_adc_nids,
9436 .capsrc_nids = alc882_capsrc_nids,
9437 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
9438 .channel_mode = alc882_3ST_6ch_modes,
9439 .need_dac_fix = 1,
9440 .input_mux = &alc882_capture_source,
9441 },
9442 [ALC882_ASUS_A7M] = {
9443 .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009444 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9445 alc882_eapd_verbs, alc880_gpio1_init_verbs,
Takashi Iwai49535502009-06-30 15:28:30 +02009446 alc882_asus_a7m_verbs },
9447 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9448 .dac_nids = alc882_dac_nids,
9449 .dig_out_nid = ALC882_DIGOUT_NID,
9450 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
9451 .channel_mode = alc880_threestack_modes,
9452 .need_dac_fix = 1,
9453 .input_mux = &alc882_capture_source,
9454 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009455 [ALC883_3ST_2ch_DIG] = {
9456 .mixers = { alc883_3ST_2ch_mixer },
9457 .init_verbs = { alc883_init_verbs },
9458 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9459 .dac_nids = alc883_dac_nids,
9460 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009461 .dig_in_nid = ALC883_DIGIN_NID,
9462 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9463 .channel_mode = alc883_3ST_2ch_modes,
9464 .input_mux = &alc883_capture_source,
9465 },
9466 [ALC883_3ST_6ch_DIG] = {
9467 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9468 .init_verbs = { alc883_init_verbs },
9469 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9470 .dac_nids = alc883_dac_nids,
9471 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009472 .dig_in_nid = ALC883_DIGIN_NID,
9473 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9474 .channel_mode = alc883_3ST_6ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02009475 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009476 .input_mux = &alc883_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02009477 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009478 [ALC883_3ST_6ch] = {
9479 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9480 .init_verbs = { alc883_init_verbs },
9481 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9482 .dac_nids = alc883_dac_nids,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009483 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9484 .channel_mode = alc883_3ST_6ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02009485 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009486 .input_mux = &alc883_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02009487 },
Jiang zhe17bba1b2008-06-04 12:11:07 +02009488 [ALC883_3ST_6ch_INTEL] = {
9489 .mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
9490 .init_verbs = { alc883_init_verbs },
9491 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9492 .dac_nids = alc883_dac_nids,
9493 .dig_out_nid = ALC883_DIGOUT_NID,
9494 .dig_in_nid = ALC883_DIGIN_NID,
Wu Fengguangf3cd3f52009-04-02 19:44:18 +08009495 .slave_dig_outs = alc883_slave_dig_outs,
Jiang zhe17bba1b2008-06-04 12:11:07 +02009496 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
9497 .channel_mode = alc883_3ST_6ch_intel_modes,
9498 .need_dac_fix = 1,
9499 .input_mux = &alc883_3stack_6ch_intel,
9500 },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009501 [ALC889A_INTEL] = {
9502 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +02009503 .init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
9504 alc_hp15_unsol_verbs },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009505 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9506 .dac_nids = alc883_dac_nids,
9507 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
9508 .adc_nids = alc889_adc_nids,
9509 .dig_out_nid = ALC883_DIGOUT_NID,
9510 .dig_in_nid = ALC883_DIGIN_NID,
9511 .slave_dig_outs = alc883_slave_dig_outs,
9512 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
9513 .channel_mode = alc889_8ch_intel_modes,
9514 .capsrc_nids = alc889_capsrc_nids,
9515 .input_mux = &alc889_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009516 .setup = alc889_automute_setup,
9517 .init_hook = alc_automute_amp,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009518 .unsol_event = alc_automute_amp_unsol_event,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009519 .need_dac_fix = 1,
9520 },
9521 [ALC889_INTEL] = {
9522 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
9523 .init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009524 alc889_eapd_verbs, alc_hp15_unsol_verbs},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009525 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9526 .dac_nids = alc883_dac_nids,
9527 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
9528 .adc_nids = alc889_adc_nids,
9529 .dig_out_nid = ALC883_DIGOUT_NID,
9530 .dig_in_nid = ALC883_DIGIN_NID,
9531 .slave_dig_outs = alc883_slave_dig_outs,
9532 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
9533 .channel_mode = alc889_8ch_intel_modes,
9534 .capsrc_nids = alc889_capsrc_nids,
9535 .input_mux = &alc889_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009536 .setup = alc889_automute_setup,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009537 .init_hook = alc889_intel_init_hook,
9538 .unsol_event = alc_automute_amp_unsol_event,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009539 .need_dac_fix = 1,
9540 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009541 [ALC883_6ST_DIG] = {
9542 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
9543 .init_verbs = { alc883_init_verbs },
9544 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9545 .dac_nids = alc883_dac_nids,
9546 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009547 .dig_in_nid = ALC883_DIGIN_NID,
9548 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
9549 .channel_mode = alc883_sixstack_modes,
9550 .input_mux = &alc883_capture_source,
9551 },
Kailang Yangccc656c2006-10-17 12:32:26 +02009552 [ALC883_TARGA_DIG] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -04009553 .mixers = { alc883_targa_mixer, alc883_chmode_mixer },
David Heidelberger005b1072009-07-09 18:45:46 +02009554 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
9555 alc883_targa_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +02009556 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9557 .dac_nids = alc883_dac_nids,
9558 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yangccc656c2006-10-17 12:32:26 +02009559 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9560 .channel_mode = alc883_3ST_6ch_modes,
9561 .need_dac_fix = 1,
9562 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -04009563 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009564 .setup = alc882_targa_setup,
9565 .init_hook = alc882_targa_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +02009566 },
9567 [ALC883_TARGA_2ch_DIG] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -04009568 .mixers = { alc883_targa_2ch_mixer},
David Heidelberger005b1072009-07-09 18:45:46 +02009569 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
9570 alc883_targa_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +02009571 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9572 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01009573 .adc_nids = alc883_adc_nids_alt,
9574 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +01009575 .capsrc_nids = alc883_capsrc_nids,
Kailang Yangccc656c2006-10-17 12:32:26 +02009576 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yangccc656c2006-10-17 12:32:26 +02009577 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9578 .channel_mode = alc883_3ST_2ch_modes,
9579 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -04009580 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009581 .setup = alc882_targa_setup,
9582 .init_hook = alc882_targa_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +02009583 },
David Heidelberger64a8be72009-06-08 16:15:18 +02009584 [ALC883_TARGA_8ch_DIG] = {
Takashi Iwaib99dba32009-09-17 18:23:00 +02009585 .mixers = { alc883_targa_mixer, alc883_targa_8ch_mixer,
9586 alc883_chmode_mixer },
David Heidelberger64a8be72009-06-08 16:15:18 +02009587 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
Sasha Alexandrc2592492009-06-16 14:52:54 -04009588 alc883_targa_verbs },
David Heidelberger64a8be72009-06-08 16:15:18 +02009589 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9590 .dac_nids = alc883_dac_nids,
9591 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9592 .adc_nids = alc883_adc_nids_rev,
9593 .capsrc_nids = alc883_capsrc_nids_rev,
9594 .dig_out_nid = ALC883_DIGOUT_NID,
9595 .dig_in_nid = ALC883_DIGIN_NID,
9596 .num_channel_mode = ARRAY_SIZE(alc883_4ST_8ch_modes),
9597 .channel_mode = alc883_4ST_8ch_modes,
9598 .need_dac_fix = 1,
9599 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -04009600 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009601 .setup = alc882_targa_setup,
9602 .init_hook = alc882_targa_automute,
David Heidelberger64a8be72009-06-08 16:15:18 +02009603 },
Vladimir Avdoninbab282b2006-08-22 13:31:58 +02009604 [ALC883_ACER] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +02009605 .mixers = { alc883_base_mixer },
Vladimir Avdoninbab282b2006-08-22 13:31:58 +02009606 /* On TravelMate laptops, GPIO 0 enables the internal speaker
9607 * and the headphone jack. Turn this on and rely on the
9608 * standard mute methods whenever the user wants to turn
9609 * these outputs off.
9610 */
9611 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
9612 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9613 .dac_nids = alc883_dac_nids,
Vladimir Avdoninbab282b2006-08-22 13:31:58 +02009614 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9615 .channel_mode = alc883_3ST_2ch_modes,
9616 .input_mux = &alc883_capture_source,
9617 },
Tobin Davis2880a862007-08-07 11:50:26 +02009618 [ALC883_ACER_ASPIRE] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +02009619 .mixers = { alc883_acer_aspire_mixer },
Kailang Yangd1a991a2007-08-15 16:21:59 +02009620 .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
Tobin Davis2880a862007-08-07 11:50:26 +02009621 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9622 .dac_nids = alc883_dac_nids,
9623 .dig_out_nid = ALC883_DIGOUT_NID,
Tobin Davis2880a862007-08-07 11:50:26 +02009624 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9625 .channel_mode = alc883_3ST_2ch_modes,
9626 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009627 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009628 .setup = alc883_acer_aspire_setup,
9629 .init_hook = alc_automute_amp,
Kailang Yangd1a991a2007-08-15 16:21:59 +02009630 },
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009631 [ALC888_ACER_ASPIRE_4930G] = {
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009632 .mixers = { alc888_base_mixer,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009633 alc883_chmode_mixer },
9634 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
9635 alc888_acer_aspire_4930g_verbs },
9636 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9637 .dac_nids = alc883_dac_nids,
9638 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9639 .adc_nids = alc883_adc_nids_rev,
9640 .capsrc_nids = alc883_capsrc_nids_rev,
9641 .dig_out_nid = ALC883_DIGOUT_NID,
9642 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9643 .channel_mode = alc883_3ST_6ch_modes,
9644 .need_dac_fix = 1,
Łukasz Wojniłowicz973b8cb2010-01-24 14:12:37 +01009645 .const_channel_count = 6,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009646 .num_mux_defs =
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009647 ARRAY_SIZE(alc888_2_capture_sources),
9648 .input_mux = alc888_2_capture_sources,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009649 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009650 .setup = alc888_acer_aspire_4930g_setup,
9651 .init_hook = alc_automute_amp,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009652 },
Tony Vroond2fd4b02009-06-21 00:40:10 +01009653 [ALC888_ACER_ASPIRE_6530G] = {
9654 .mixers = { alc888_acer_aspire_6530_mixer },
9655 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
9656 alc888_acer_aspire_6530g_verbs },
9657 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9658 .dac_nids = alc883_dac_nids,
9659 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9660 .adc_nids = alc883_adc_nids_rev,
9661 .capsrc_nids = alc883_capsrc_nids_rev,
9662 .dig_out_nid = ALC883_DIGOUT_NID,
9663 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9664 .channel_mode = alc883_3ST_2ch_modes,
9665 .num_mux_defs =
9666 ARRAY_SIZE(alc888_2_capture_sources),
9667 .input_mux = alc888_acer_aspire_6530_sources,
9668 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009669 .setup = alc888_acer_aspire_6530g_setup,
9670 .init_hook = alc_automute_amp,
Tony Vroond2fd4b02009-06-21 00:40:10 +01009671 },
Hector Martin3b315d72009-06-02 10:54:19 +02009672 [ALC888_ACER_ASPIRE_8930G] = {
Hector Martin556eea92009-12-20 22:51:23 +01009673 .mixers = { alc889_acer_aspire_8930g_mixer,
Hector Martin3b315d72009-06-02 10:54:19 +02009674 alc883_chmode_mixer },
9675 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
Hector Martin0f86a222009-12-20 22:51:18 +01009676 alc889_acer_aspire_8930g_verbs,
9677 alc889_eapd_verbs},
Hector Martin3b315d72009-06-02 10:54:19 +02009678 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9679 .dac_nids = alc883_dac_nids,
Hector Martin018df412009-06-04 00:13:40 +02009680 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
9681 .adc_nids = alc889_adc_nids,
9682 .capsrc_nids = alc889_capsrc_nids,
Hector Martin3b315d72009-06-02 10:54:19 +02009683 .dig_out_nid = ALC883_DIGOUT_NID,
9684 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9685 .channel_mode = alc883_3ST_6ch_modes,
9686 .need_dac_fix = 1,
9687 .const_channel_count = 6,
9688 .num_mux_defs =
Hector Martin018df412009-06-04 00:13:40 +02009689 ARRAY_SIZE(alc889_capture_sources),
9690 .input_mux = alc889_capture_sources,
Hector Martin3b315d72009-06-02 10:54:19 +02009691 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009692 .setup = alc889_acer_aspire_8930g_setup,
9693 .init_hook = alc_automute_amp,
Hector Martinf5de24b2009-12-20 22:51:31 +01009694#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05009695 .power_hook = alc_power_eapd,
Hector Martinf5de24b2009-12-20 22:51:31 +01009696#endif
Hector Martin3b315d72009-06-02 10:54:19 +02009697 },
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009698 [ALC888_ACER_ASPIRE_7730G] = {
9699 .mixers = { alc883_3ST_6ch_mixer,
9700 alc883_chmode_mixer },
9701 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
9702 alc888_acer_aspire_7730G_verbs },
9703 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9704 .dac_nids = alc883_dac_nids,
9705 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9706 .adc_nids = alc883_adc_nids_rev,
9707 .capsrc_nids = alc883_capsrc_nids_rev,
9708 .dig_out_nid = ALC883_DIGOUT_NID,
9709 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9710 .channel_mode = alc883_3ST_6ch_modes,
9711 .need_dac_fix = 1,
9712 .const_channel_count = 6,
9713 .input_mux = &alc883_capture_source,
9714 .unsol_event = alc_automute_amp_unsol_event,
9715 .setup = alc888_acer_aspire_6530g_setup,
9716 .init_hook = alc_automute_amp,
9717 },
Tobin Davisc07584c2006-10-13 12:32:16 +02009718 [ALC883_MEDION] = {
9719 .mixers = { alc883_fivestack_mixer,
9720 alc883_chmode_mixer },
9721 .init_verbs = { alc883_init_verbs,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009722 alc883_medion_eapd_verbs },
Tobin Davisc07584c2006-10-13 12:32:16 +02009723 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9724 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01009725 .adc_nids = alc883_adc_nids_alt,
9726 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +01009727 .capsrc_nids = alc883_capsrc_nids,
Tobin Davisc07584c2006-10-13 12:32:16 +02009728 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
9729 .channel_mode = alc883_sixstack_modes,
9730 .input_mux = &alc883_capture_source,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009731 },
Kailang Yang272a5272007-05-14 11:00:38 +02009732 [ALC883_MEDION_MD2] = {
9733 .mixers = { alc883_medion_md2_mixer},
9734 .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs},
9735 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9736 .dac_nids = alc883_dac_nids,
9737 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang272a5272007-05-14 11:00:38 +02009738 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9739 .channel_mode = alc883_3ST_2ch_modes,
9740 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009741 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009742 .setup = alc883_medion_md2_setup,
9743 .init_hook = alc_automute_amp,
Kailang Yangea1fb292008-08-26 12:58:38 +02009744 },
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009745 [ALC883_LAPTOP_EAPD] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +02009746 .mixers = { alc883_base_mixer },
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009747 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
9748 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9749 .dac_nids = alc883_dac_nids,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01009750 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9751 .channel_mode = alc883_3ST_2ch_modes,
9752 .input_mux = &alc883_capture_source,
9753 },
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04309754 [ALC883_CLEVO_M540R] = {
9755 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9756 .init_verbs = { alc883_init_verbs, alc883_clevo_m540r_verbs },
9757 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9758 .dac_nids = alc883_dac_nids,
9759 .dig_out_nid = ALC883_DIGOUT_NID,
9760 .dig_in_nid = ALC883_DIGIN_NID,
9761 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_clevo_modes),
9762 .channel_mode = alc883_3ST_6ch_clevo_modes,
9763 .need_dac_fix = 1,
9764 .input_mux = &alc883_capture_source,
9765 /* This machine has the hardware HP auto-muting, thus
9766 * we need no software mute via unsol event
9767 */
9768 },
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009769 [ALC883_CLEVO_M720] = {
9770 .mixers = { alc883_clevo_m720_mixer },
9771 .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
Jiang zhe368c7a92008-03-04 11:20:33 +01009772 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9773 .dac_nids = alc883_dac_nids,
9774 .dig_out_nid = ALC883_DIGOUT_NID,
9775 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9776 .channel_mode = alc883_3ST_2ch_modes,
9777 .input_mux = &alc883_capture_source,
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009778 .unsol_event = alc883_clevo_m720_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009779 .setup = alc883_clevo_m720_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009780 .init_hook = alc883_clevo_m720_init_hook,
Jiang zhe368c7a92008-03-04 11:20:33 +01009781 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009782 [ALC883_LENOVO_101E_2ch] = {
9783 .mixers = { alc883_lenovo_101e_2ch_mixer},
9784 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
9785 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9786 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01009787 .adc_nids = alc883_adc_nids_alt,
9788 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +01009789 .capsrc_nids = alc883_capsrc_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009790 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9791 .channel_mode = alc883_3ST_2ch_modes,
9792 .input_mux = &alc883_lenovo_101e_capture_source,
9793 .unsol_event = alc883_lenovo_101e_unsol_event,
9794 .init_hook = alc883_lenovo_101e_all_automute,
9795 },
Kailang Yang272a5272007-05-14 11:00:38 +02009796 [ALC883_LENOVO_NB0763] = {
9797 .mixers = { alc883_lenovo_nb0763_mixer },
9798 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
9799 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9800 .dac_nids = alc883_dac_nids,
Kailang Yang272a5272007-05-14 11:00:38 +02009801 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9802 .channel_mode = alc883_3ST_2ch_modes,
9803 .need_dac_fix = 1,
9804 .input_mux = &alc883_lenovo_nb0763_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009805 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009806 .setup = alc883_medion_md2_setup,
9807 .init_hook = alc_automute_amp,
Kailang Yang272a5272007-05-14 11:00:38 +02009808 },
9809 [ALC888_LENOVO_MS7195_DIG] = {
9810 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9811 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
9812 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9813 .dac_nids = alc883_dac_nids,
9814 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang272a5272007-05-14 11:00:38 +02009815 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9816 .channel_mode = alc883_3ST_6ch_modes,
9817 .need_dac_fix = 1,
9818 .input_mux = &alc883_capture_source,
9819 .unsol_event = alc883_lenovo_ms7195_unsol_event,
9820 .init_hook = alc888_lenovo_ms7195_front_automute,
Kailang Yang189609a2007-08-20 11:31:23 +02009821 },
9822 [ALC883_HAIER_W66] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -04009823 .mixers = { alc883_targa_2ch_mixer},
Kailang Yang189609a2007-08-20 11:31:23 +02009824 .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
9825 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9826 .dac_nids = alc883_dac_nids,
9827 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang189609a2007-08-20 11:31:23 +02009828 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9829 .channel_mode = alc883_3ST_2ch_modes,
9830 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009831 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009832 .setup = alc883_haier_w66_setup,
9833 .init_hook = alc_automute_amp,
Herton Ronaldo Krzesinskieea64192008-03-20 12:14:59 +01009834 },
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009835 [ALC888_3ST_HP] = {
Herton Ronaldo Krzesinskieea64192008-03-20 12:14:59 +01009836 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009837 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009838 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9839 .dac_nids = alc883_dac_nids,
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009840 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
9841 .channel_mode = alc888_3st_hp_modes,
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009842 .need_dac_fix = 1,
9843 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009844 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009845 .setup = alc888_3st_hp_setup,
9846 .init_hook = alc_automute_amp,
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009847 },
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009848 [ALC888_6ST_DELL] = {
Herton Ronaldo Krzesinskif24dbdc2008-03-20 12:14:28 +01009849 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009850 .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
9851 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9852 .dac_nids = alc883_dac_nids,
9853 .dig_out_nid = ALC883_DIGOUT_NID,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009854 .dig_in_nid = ALC883_DIGIN_NID,
9855 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
9856 .channel_mode = alc883_sixstack_modes,
9857 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009858 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009859 .setup = alc888_6st_dell_setup,
9860 .init_hook = alc_automute_amp,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009861 },
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01009862 [ALC883_MITAC] = {
9863 .mixers = { alc883_mitac_mixer },
9864 .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
9865 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9866 .dac_nids = alc883_dac_nids,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01009867 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9868 .channel_mode = alc883_3ST_2ch_modes,
9869 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009870 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009871 .setup = alc883_mitac_setup,
9872 .init_hook = alc_automute_amp,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01009873 },
Jiang zhefb97dc62008-03-06 11:07:11 +01009874 [ALC883_FUJITSU_PI2515] = {
9875 .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
9876 .init_verbs = { alc883_init_verbs,
9877 alc883_2ch_fujitsu_pi2515_verbs},
9878 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9879 .dac_nids = alc883_dac_nids,
9880 .dig_out_nid = ALC883_DIGOUT_NID,
9881 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9882 .channel_mode = alc883_3ST_2ch_modes,
9883 .input_mux = &alc883_fujitsu_pi2515_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009884 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009885 .setup = alc883_2ch_fujitsu_pi2515_setup,
9886 .init_hook = alc_automute_amp,
Jiang zhefb97dc62008-03-06 11:07:11 +01009887 },
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009888 [ALC888_FUJITSU_XA3530] = {
9889 .mixers = { alc888_base_mixer, alc883_chmode_mixer },
9890 .init_verbs = { alc883_init_verbs,
9891 alc888_fujitsu_xa3530_verbs },
9892 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9893 .dac_nids = alc883_dac_nids,
9894 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
9895 .adc_nids = alc883_adc_nids_rev,
9896 .capsrc_nids = alc883_capsrc_nids_rev,
9897 .dig_out_nid = ALC883_DIGOUT_NID,
9898 .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
9899 .channel_mode = alc888_4ST_8ch_intel_modes,
9900 .num_mux_defs =
9901 ARRAY_SIZE(alc888_2_capture_sources),
9902 .input_mux = alc888_2_capture_sources,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009903 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009904 .setup = alc888_fujitsu_xa3530_setup,
9905 .init_hook = alc_automute_amp,
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009906 },
Kailang Yange2757d52008-08-26 13:17:46 +02009907 [ALC888_LENOVO_SKY] = {
9908 .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
9909 .init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
9910 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9911 .dac_nids = alc883_dac_nids,
9912 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yange2757d52008-08-26 13:17:46 +02009913 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
9914 .channel_mode = alc883_sixstack_modes,
9915 .need_dac_fix = 1,
9916 .input_mux = &alc883_lenovo_sky_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009917 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009918 .setup = alc888_lenovo_sky_setup,
9919 .init_hook = alc_automute_amp,
Kailang Yange2757d52008-08-26 13:17:46 +02009920 },
9921 [ALC888_ASUS_M90V] = {
9922 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9923 .init_verbs = { alc883_init_verbs, alc888_asus_m90v_verbs },
9924 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9925 .dac_nids = alc883_dac_nids,
9926 .dig_out_nid = ALC883_DIGOUT_NID,
9927 .dig_in_nid = ALC883_DIGIN_NID,
9928 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9929 .channel_mode = alc883_3ST_6ch_modes,
9930 .need_dac_fix = 1,
9931 .input_mux = &alc883_fujitsu_pi2515_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009932 .unsol_event = alc_sku_unsol_event,
9933 .setup = alc883_mode2_setup,
9934 .init_hook = alc_inithook,
Kailang Yange2757d52008-08-26 13:17:46 +02009935 },
9936 [ALC888_ASUS_EEE1601] = {
9937 .mixers = { alc883_asus_eee1601_mixer },
Takashi Iwaif9e336f2008-10-31 16:37:07 +01009938 .cap_mixer = alc883_asus_eee1601_cap_mixer,
Kailang Yange2757d52008-08-26 13:17:46 +02009939 .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
9940 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9941 .dac_nids = alc883_dac_nids,
9942 .dig_out_nid = ALC883_DIGOUT_NID,
9943 .dig_in_nid = ALC883_DIGIN_NID,
9944 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9945 .channel_mode = alc883_3ST_2ch_modes,
9946 .need_dac_fix = 1,
9947 .input_mux = &alc883_asus_eee1601_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009948 .unsol_event = alc_sku_unsol_event,
Kailang Yange2757d52008-08-26 13:17:46 +02009949 .init_hook = alc883_eee1601_inithook,
9950 },
Wu Fengguang3ab90932008-11-17 09:51:09 +01009951 [ALC1200_ASUS_P5Q] = {
9952 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
9953 .init_verbs = { alc883_init_verbs },
9954 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9955 .dac_nids = alc883_dac_nids,
9956 .dig_out_nid = ALC1200_DIGOUT_NID,
9957 .dig_in_nid = ALC883_DIGIN_NID,
Wu Fengguangb25c9da2009-02-06 15:02:27 +08009958 .slave_dig_outs = alc1200_slave_dig_outs,
Wu Fengguang3ab90932008-11-17 09:51:09 +01009959 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
9960 .channel_mode = alc883_sixstack_modes,
9961 .input_mux = &alc883_capture_source,
9962 },
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009963 [ALC889A_MB31] = {
9964 .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
9965 .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
9966 alc880_gpio1_init_verbs },
9967 .adc_nids = alc883_adc_nids,
9968 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
Takashi Iwai035eb0c2009-12-17 15:00:26 +01009969 .capsrc_nids = alc883_capsrc_nids,
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009970 .dac_nids = alc883_dac_nids,
9971 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9972 .channel_mode = alc889A_mb31_6ch_modes,
9973 .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
9974 .input_mux = &alc889A_mb31_capture_source,
9975 .dig_out_nid = ALC883_DIGOUT_NID,
9976 .unsol_event = alc889A_mb31_unsol_event,
9977 .init_hook = alc889A_mb31_automute,
9978 },
Guido Günther3e1647c2009-06-05 00:47:26 +02009979 [ALC883_SONY_VAIO_TT] = {
9980 .mixers = { alc883_vaiott_mixer },
9981 .init_verbs = { alc883_init_verbs, alc883_vaiott_verbs },
9982 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9983 .dac_nids = alc883_dac_nids,
9984 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9985 .channel_mode = alc883_3ST_2ch_modes,
9986 .input_mux = &alc883_capture_source,
9987 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009988 .setup = alc883_vaiott_setup,
9989 .init_hook = alc_automute_amp,
Guido Günther3e1647c2009-06-05 00:47:26 +02009990 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009991};
9992
9993
9994/*
Takashi Iwai49535502009-06-30 15:28:30 +02009995 * Pin config fixes
9996 */
9997enum {
9998 PINFIX_ABIT_AW9D_MAX
9999};
10000
10001static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
10002 { 0x15, 0x01080104 }, /* side */
10003 { 0x16, 0x01011012 }, /* rear */
10004 { 0x17, 0x01016011 }, /* clfe */
10005 { }
10006};
10007
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010008static const struct alc_fixup alc882_fixups[] = {
10009 [PINFIX_ABIT_AW9D_MAX] = {
10010 .pins = alc882_abit_aw9d_pinfix
10011 },
Takashi Iwai49535502009-06-30 15:28:30 +020010012};
10013
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010014static struct snd_pci_quirk alc882_fixup_tbl[] = {
Takashi Iwai49535502009-06-30 15:28:30 +020010015 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
10016 {}
10017};
10018
10019/*
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010020 * BIOS auto configuration
10021 */
Takashi Iwai05f5f472009-08-25 13:10:18 +020010022static int alc882_auto_create_input_ctls(struct hda_codec *codec,
10023 const struct auto_pin_cfg *cfg)
10024{
10025 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x23, 0x22);
10026}
10027
Takashi Iwai49535502009-06-30 15:28:30 +020010028static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010029 hda_nid_t nid, int pin_type,
10030 int dac_idx)
10031{
10032 /* set as output */
10033 struct alc_spec *spec = codec->spec;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010034 int idx;
10035
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010036 alc_set_pin_output(codec, nid, pin_type);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010037 if (spec->multiout.dac_nids[dac_idx] == 0x25)
10038 idx = 4;
10039 else
10040 idx = spec->multiout.dac_nids[dac_idx] - 2;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010041 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
10042
10043}
10044
Takashi Iwai49535502009-06-30 15:28:30 +020010045static void alc882_auto_init_multi_out(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010046{
10047 struct alc_spec *spec = codec->spec;
10048 int i;
10049
10050 for (i = 0; i <= HDA_SIDE; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010051 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020010052 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010053 if (nid)
Takashi Iwai49535502009-06-30 15:28:30 +020010054 alc882_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010055 i);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010056 }
10057}
10058
Takashi Iwai49535502009-06-30 15:28:30 +020010059static void alc882_auto_init_hp_out(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010060{
10061 struct alc_spec *spec = codec->spec;
10062 hda_nid_t pin;
10063
Takashi Iwaieb06ed82006-09-20 17:10:27 +020010064 pin = spec->autocfg.hp_pins[0];
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010065 if (pin) /* connect to front */
10066 /* use dac 0 */
Takashi Iwai49535502009-06-30 15:28:30 +020010067 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010068 pin = spec->autocfg.speaker_pins[0];
10069 if (pin)
Takashi Iwai49535502009-06-30 15:28:30 +020010070 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010071}
10072
Takashi Iwai49535502009-06-30 15:28:30 +020010073static void alc882_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010074{
10075 struct alc_spec *spec = codec->spec;
10076 int i;
10077
10078 for (i = 0; i < AUTO_PIN_LAST; i++) {
10079 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai49535502009-06-30 15:28:30 +020010080 if (!nid)
10081 continue;
Takashi Iwai0d971c92009-06-30 16:11:11 +020010082 alc_set_input_pin(codec, nid, i);
Takashi Iwai49535502009-06-30 15:28:30 +020010083 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
10084 snd_hda_codec_write(codec, nid, 0,
10085 AC_VERB_SET_AMP_GAIN_MUTE,
10086 AMP_OUT_MUTE);
10087 }
10088}
10089
10090static void alc882_auto_init_input_src(struct hda_codec *codec)
10091{
10092 struct alc_spec *spec = codec->spec;
10093 int c;
10094
10095 for (c = 0; c < spec->num_adc_nids; c++) {
10096 hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
10097 hda_nid_t nid = spec->capsrc_nids[c];
10098 unsigned int mux_idx;
10099 const struct hda_input_mux *imux;
10100 int conns, mute, idx, item;
10101
10102 conns = snd_hda_get_connections(codec, nid, conn_list,
10103 ARRAY_SIZE(conn_list));
10104 if (conns < 0)
10105 continue;
10106 mux_idx = c >= spec->num_mux_defs ? 0 : c;
10107 imux = &spec->input_mux[mux_idx];
10108 for (idx = 0; idx < conns; idx++) {
10109 /* if the current connection is the selected one,
10110 * unmute it as default - otherwise mute it
10111 */
10112 mute = AMP_IN_MUTE(idx);
10113 for (item = 0; item < imux->num_items; item++) {
10114 if (imux->items[item].index == idx) {
10115 if (spec->cur_mux[c] == item)
10116 mute = AMP_IN_UNMUTE(idx);
10117 break;
10118 }
10119 }
10120 /* check if we have a selector or mixer
10121 * we could check for the widget type instead, but
10122 * just check for Amp-In presence (in case of mixer
10123 * without amp-in there is something wrong, this
10124 * function shouldn't be used or capsrc nid is wrong)
10125 */
10126 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010127 snd_hda_codec_write(codec, nid, 0,
10128 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwai49535502009-06-30 15:28:30 +020010129 mute);
10130 else if (mute != AMP_IN_MUTE(idx))
10131 snd_hda_codec_write(codec, nid, 0,
10132 AC_VERB_SET_CONNECT_SEL,
10133 idx);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010134 }
10135 }
10136}
10137
Takashi Iwai49535502009-06-30 15:28:30 +020010138/* add mic boosts if needed */
10139static int alc_auto_add_mic_boost(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010140{
10141 struct alc_spec *spec = codec->spec;
Takashi Iwai49535502009-06-30 15:28:30 +020010142 int err;
10143 hda_nid_t nid;
10144
10145 nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
10146 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
10147 err = add_control(spec, ALC_CTL_WIDGET_VOL,
10148 "Mic Boost",
10149 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
10150 if (err < 0)
10151 return err;
10152 }
10153 nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
10154 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
10155 err = add_control(spec, ALC_CTL_WIDGET_VOL,
10156 "Front Mic Boost",
10157 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
10158 if (err < 0)
10159 return err;
10160 }
10161 return 0;
10162}
10163
10164/* almost identical with ALC880 parser... */
10165static int alc882_parse_auto_config(struct hda_codec *codec)
10166{
10167 struct alc_spec *spec = codec->spec;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010168 static hda_nid_t alc882_ignore[] = { 0x1d, 0 };
10169 int i, err;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010170
Takashi Iwai05f5f472009-08-25 13:10:18 +020010171 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
10172 alc882_ignore);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010173 if (err < 0)
10174 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010175 if (!spec->autocfg.line_outs)
10176 return 0; /* can't find valid BIOS pin config */
10177
10178 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
10179 if (err < 0)
10180 return err;
10181 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
10182 if (err < 0)
10183 return err;
10184 err = alc880_auto_create_extra_out(spec,
10185 spec->autocfg.speaker_pins[0],
10186 "Speaker");
10187 if (err < 0)
10188 return err;
10189 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
10190 "Headphone");
10191 if (err < 0)
10192 return err;
10193 err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
10194 if (err < 0)
10195 return err;
10196
10197 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
10198
10199 /* check multiple SPDIF-out (for recent codecs) */
10200 for (i = 0; i < spec->autocfg.dig_outs; i++) {
10201 hda_nid_t dig_nid;
10202 err = snd_hda_get_connections(codec,
10203 spec->autocfg.dig_out_pins[i],
10204 &dig_nid, 1);
10205 if (err < 0)
10206 continue;
10207 if (!i)
10208 spec->multiout.dig_out_nid = dig_nid;
10209 else {
10210 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
Roel Kluin71121d9f2009-11-10 20:11:55 +010010211 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
Takashi Iwai05f5f472009-08-25 13:10:18 +020010212 break;
Roel Kluin71121d9f2009-11-10 20:11:55 +010010213 spec->slave_dig_outs[i - 1] = dig_nid;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010214 }
10215 }
10216 if (spec->autocfg.dig_in_pin)
10217 spec->dig_in_nid = ALC880_DIGIN_NID;
10218
10219 if (spec->kctls.list)
10220 add_mixer(spec, spec->kctls.list);
10221
10222 add_verb(spec, alc883_auto_init_verbs);
10223 /* if ADC 0x07 is available, initialize it, too */
10224 if (get_wcaps_type(get_wcaps(codec, 0x07)) == AC_WID_AUD_IN)
10225 add_verb(spec, alc882_adc1_init_verbs);
10226
10227 spec->num_mux_defs = 1;
10228 spec->input_mux = &spec->private_imux[0];
10229
Kailang Yang6227cdc2010-02-25 08:36:52 +010010230 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai776e1842007-08-29 15:07:11 +020010231
10232 err = alc_auto_add_mic_boost(codec);
10233 if (err < 0)
10234 return err;
10235
Takashi Iwai776e1842007-08-29 15:07:11 +020010236 return 1; /* config found */
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010237}
10238
10239/* additional initialization for auto-configuration model */
Takashi Iwai49535502009-06-30 15:28:30 +020010240static void alc882_auto_init(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010241{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010242 struct alc_spec *spec = codec->spec;
Takashi Iwai49535502009-06-30 15:28:30 +020010243 alc882_auto_init_multi_out(codec);
10244 alc882_auto_init_hp_out(codec);
10245 alc882_auto_init_analog_input(codec);
10246 alc882_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010247 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020010248 alc_inithook(codec);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010249}
10250
Takashi Iwai49535502009-06-30 15:28:30 +020010251static int patch_alc882(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010252{
10253 struct alc_spec *spec;
10254 int err, board_config;
10255
10256 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
10257 if (spec == NULL)
10258 return -ENOMEM;
10259
10260 codec->spec = spec;
10261
Takashi Iwai49535502009-06-30 15:28:30 +020010262 switch (codec->vendor_id) {
10263 case 0x10ec0882:
10264 case 0x10ec0885:
10265 break;
10266 default:
10267 /* ALC883 and variants */
10268 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
10269 break;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010270 }
10271
Takashi Iwai49535502009-06-30 15:28:30 +020010272 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
10273 alc882_models,
10274 alc882_cfg_tbl);
10275
10276 if (board_config < 0 || board_config >= ALC882_MODEL_LAST)
10277 board_config = snd_hda_check_board_codec_sid_config(codec,
10278 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
10279
10280 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020010281 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
Takashi Iwai49535502009-06-30 15:28:30 +020010282 codec->chip_name);
10283 board_config = ALC882_AUTO;
10284 }
10285
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010286 alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups);
Takashi Iwai49535502009-06-30 15:28:30 +020010287
10288 if (board_config == ALC882_AUTO) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010289 /* automatic parse from the BIOS config */
Takashi Iwai49535502009-06-30 15:28:30 +020010290 err = alc882_parse_auto_config(codec);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010291 if (err < 0) {
10292 alc_free(codec);
10293 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010294 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010295 printk(KERN_INFO
10296 "hda_codec: Cannot set up configuration "
10297 "from BIOS. Using base mode...\n");
Takashi Iwai49535502009-06-30 15:28:30 +020010298 board_config = ALC882_3ST_DIG;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010299 }
10300 }
10301
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090010302 err = snd_hda_attach_beep_device(codec, 0x1);
10303 if (err < 0) {
10304 alc_free(codec);
10305 return err;
10306 }
10307
Takashi Iwai49535502009-06-30 15:28:30 +020010308 if (board_config != ALC882_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020010309 setup_preset(codec, &alc882_presets[board_config]);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010310
Takashi Iwai49535502009-06-30 15:28:30 +020010311 spec->stream_analog_playback = &alc882_pcm_analog_playback;
10312 spec->stream_analog_capture = &alc882_pcm_analog_capture;
10313 /* FIXME: setup DAC5 */
10314 /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
10315 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
10316
10317 spec->stream_digital_playback = &alc882_pcm_digital_playback;
10318 spec->stream_digital_capture = &alc882_pcm_digital_capture;
10319
10320 if (codec->vendor_id == 0x10ec0888)
Takashi Iwai4a79ba32009-04-22 16:31:35 +020010321 spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */
Takashi Iwai49535502009-06-30 15:28:30 +020010322
10323 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010324 int i, j;
Takashi Iwai49535502009-06-30 15:28:30 +020010325 spec->num_adc_nids = 0;
10326 for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010327 const struct hda_input_mux *imux = spec->input_mux;
Takashi Iwai49535502009-06-30 15:28:30 +020010328 hda_nid_t cap;
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010329 hda_nid_t items[16];
Takashi Iwai49535502009-06-30 15:28:30 +020010330 hda_nid_t nid = alc882_adc_nids[i];
10331 unsigned int wcap = get_wcaps(codec, nid);
10332 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020010333 wcap = get_wcaps_type(wcap);
Takashi Iwai49535502009-06-30 15:28:30 +020010334 if (wcap != AC_WID_AUD_IN)
10335 continue;
10336 spec->private_adc_nids[spec->num_adc_nids] = nid;
10337 err = snd_hda_get_connections(codec, nid, &cap, 1);
10338 if (err < 0)
10339 continue;
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010340 err = snd_hda_get_connections(codec, cap, items,
10341 ARRAY_SIZE(items));
10342 if (err < 0)
10343 continue;
10344 for (j = 0; j < imux->num_items; j++)
10345 if (imux->items[j].index >= err)
10346 break;
10347 if (j < imux->num_items)
10348 continue;
Takashi Iwai49535502009-06-30 15:28:30 +020010349 spec->private_capsrc_nids[spec->num_adc_nids] = cap;
10350 spec->num_adc_nids++;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020010351 }
Takashi Iwai49535502009-06-30 15:28:30 +020010352 spec->adc_nids = spec->private_adc_nids;
10353 spec->capsrc_nids = spec->private_capsrc_nids;
Kailang Yang2f893282008-05-27 12:14:47 +020010354 }
10355
Takashi Iwaib59bdf32009-08-11 09:47:30 +020010356 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010010357 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010358
Takashi Iwai2134ea42008-01-10 16:53:55 +010010359 spec->vmaster_nid = 0x0c;
10360
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010361 codec->patch_ops = alc_patch_ops;
Takashi Iwai49535502009-06-30 15:28:30 +020010362 if (board_config == ALC882_AUTO)
10363 spec->init_hook = alc882_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020010364#ifdef CONFIG_SND_HDA_POWER_SAVE
10365 if (!spec->loopback.amplist)
Takashi Iwai49535502009-06-30 15:28:30 +020010366 spec->loopback.amplist = alc882_loopbacks;
Takashi Iwaicb53c622007-08-10 17:21:45 +020010367#endif
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010368
10369 return 0;
10370}
10371
Takashi Iwai49535502009-06-30 15:28:30 +020010372
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010373/*
Kailang Yangdf694da2005-12-05 19:42:22 +010010374 * ALC262 support
10375 */
10376
10377#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
10378#define ALC262_DIGIN_NID ALC880_DIGIN_NID
10379
10380#define alc262_dac_nids alc260_dac_nids
10381#define alc262_adc_nids alc882_adc_nids
10382#define alc262_adc_nids_alt alc882_adc_nids_alt
Takashi Iwai88c71a92008-02-14 17:27:17 +010010383#define alc262_capsrc_nids alc882_capsrc_nids
10384#define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
Kailang Yangdf694da2005-12-05 19:42:22 +010010385
10386#define alc262_modes alc260_modes
Takashi Iwaic5f2ea02005-12-06 18:54:31 +010010387#define alc262_capture_source alc882_capture_source
Kailang Yangdf694da2005-12-05 19:42:22 +010010388
Kailang Yang4e555fe2008-08-26 13:05:55 +020010389static hda_nid_t alc262_dmic_adc_nids[1] = {
10390 /* ADC0 */
10391 0x09
10392};
10393
10394static hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
10395
Kailang Yangdf694da2005-12-05 19:42:22 +010010396static struct snd_kcontrol_new alc262_base_mixer[] = {
10397 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10398 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
10399 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10400 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10401 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10402 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10403 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10404 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010405 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010406 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10407 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010408 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010409 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
10410 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10411 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
10412 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010413 { } /* end */
Takashi Iwai834be882006-03-01 14:16:17 +010010414};
10415
Takashi Iwaice875f02008-01-28 18:17:43 +010010416/* update HP, line and mono-out pins according to the master switch */
10417static void alc262_hp_master_update(struct hda_codec *codec)
10418{
10419 struct alc_spec *spec = codec->spec;
10420 int val = spec->master_sw;
10421
10422 /* HP & line-out */
10423 snd_hda_codec_write_cache(codec, 0x1b, 0,
10424 AC_VERB_SET_PIN_WIDGET_CONTROL,
10425 val ? PIN_HP : 0);
10426 snd_hda_codec_write_cache(codec, 0x15, 0,
10427 AC_VERB_SET_PIN_WIDGET_CONTROL,
10428 val ? PIN_HP : 0);
10429 /* mono (speaker) depending on the HP jack sense */
10430 val = val && !spec->jack_present;
10431 snd_hda_codec_write_cache(codec, 0x16, 0,
10432 AC_VERB_SET_PIN_WIDGET_CONTROL,
10433 val ? PIN_OUT : 0);
10434}
10435
10436static void alc262_hp_bpc_automute(struct hda_codec *codec)
10437{
10438 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +080010439
10440 spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
Takashi Iwaice875f02008-01-28 18:17:43 +010010441 alc262_hp_master_update(codec);
10442}
10443
10444static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)
10445{
10446 if ((res >> 26) != ALC880_HP_EVENT)
10447 return;
10448 alc262_hp_bpc_automute(codec);
10449}
10450
10451static void alc262_hp_wildwest_automute(struct hda_codec *codec)
10452{
10453 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +080010454
10455 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwaice875f02008-01-28 18:17:43 +010010456 alc262_hp_master_update(codec);
10457}
10458
10459static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,
10460 unsigned int res)
10461{
10462 if ((res >> 26) != ALC880_HP_EVENT)
10463 return;
10464 alc262_hp_wildwest_automute(codec);
10465}
10466
Takashi Iwaib72519b2009-05-08 14:31:55 +020010467#define alc262_hp_master_sw_get alc260_hp_master_sw_get
Takashi Iwaice875f02008-01-28 18:17:43 +010010468
10469static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
10470 struct snd_ctl_elem_value *ucontrol)
10471{
10472 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10473 struct alc_spec *spec = codec->spec;
10474 int val = !!*ucontrol->value.integer.value;
10475
10476 if (val == spec->master_sw)
10477 return 0;
10478 spec->master_sw = val;
10479 alc262_hp_master_update(codec);
10480 return 1;
10481}
10482
Takashi Iwaib72519b2009-05-08 14:31:55 +020010483#define ALC262_HP_MASTER_SWITCH \
10484 { \
10485 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
10486 .name = "Master Playback Switch", \
10487 .info = snd_ctl_boolean_mono_info, \
10488 .get = alc262_hp_master_sw_get, \
10489 .put = alc262_hp_master_sw_put, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010010490 }, \
10491 { \
10492 .iface = NID_MAPPING, \
10493 .name = "Master Playback Switch", \
10494 .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \
Takashi Iwaib72519b2009-05-08 14:31:55 +020010495 }
10496
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010010497
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010498static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
Takashi Iwaib72519b2009-05-08 14:31:55 +020010499 ALC262_HP_MASTER_SWITCH,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010500 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10501 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10502 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Takashi Iwaice875f02008-01-28 18:17:43 +010010503 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
10504 HDA_OUTPUT),
10505 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
10506 HDA_OUTPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010507 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10508 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010509 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010510 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10511 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010512 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010513 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10514 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10515 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10516 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010517 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
10518 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
10519 { } /* end */
10520};
10521
Kailang Yangcd7509a2007-01-26 18:33:17 +010010522static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
Takashi Iwaib72519b2009-05-08 14:31:55 +020010523 ALC262_HP_MASTER_SWITCH,
Kailang Yangcd7509a2007-01-26 18:33:17 +010010524 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10525 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10526 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
10527 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwaice875f02008-01-28 18:17:43 +010010528 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
10529 HDA_OUTPUT),
10530 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
10531 HDA_OUTPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010532 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
10533 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010534 HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010535 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
10536 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
10537 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10538 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010539 { } /* end */
10540};
10541
10542static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
10543 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10544 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010545 HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010546 { } /* end */
10547};
10548
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010549/* mute/unmute internal speaker according to the hp jack and mute state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010550static void alc262_hp_t5735_setup(struct hda_codec *codec)
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010551{
10552 struct alc_spec *spec = codec->spec;
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010553
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010554 spec->autocfg.hp_pins[0] = 0x15;
Takashi Iwaidc99be42010-01-20 08:35:06 +010010555 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010556}
10557
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010558static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
Takashi Iwai86cd9292008-01-28 18:09:56 +010010559 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10560 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Kailang Yang66d2a9d2007-11-14 12:06:21 +010010561 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
10562 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10563 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10564 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10565 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10566 { } /* end */
10567};
10568
10569static struct hda_verb alc262_hp_t5735_verbs[] = {
10570 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10571 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10572
10573 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
10574 { }
10575};
10576
Kailang Yang8c427222008-01-10 13:03:59 +010010577static struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
Takashi Iwaif2f48e12008-01-28 18:14:43 +010010578 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10579 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +010010580 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
10581 HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010010582 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
10583 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
10584 { } /* end */
10585};
10586
10587static struct hda_verb alc262_hp_rp5700_verbs[] = {
10588 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10589 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10590 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10591 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10592 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10593 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
10594 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
10595 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
10596 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
10597 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
10598 {}
10599};
10600
10601static struct hda_input_mux alc262_hp_rp5700_capture_source = {
10602 .num_items = 1,
10603 .items = {
10604 { "Line", 0x1 },
10605 },
10606};
10607
Takashi Iwai42171c12009-05-08 14:11:43 +020010608/* bind hp and internal speaker mute (with plug check) as master switch */
10609static void alc262_hippo_master_update(struct hda_codec *codec)
10610{
10611 struct alc_spec *spec = codec->spec;
10612 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
10613 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
10614 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
10615 unsigned int mute;
10616
10617 /* HP */
10618 mute = spec->master_sw ? 0 : HDA_AMP_MUTE;
10619 snd_hda_codec_amp_stereo(codec, hp_nid, HDA_OUTPUT, 0,
10620 HDA_AMP_MUTE, mute);
10621 /* mute internal speaker per jack sense */
10622 if (spec->jack_present)
10623 mute = HDA_AMP_MUTE;
10624 if (line_nid)
10625 snd_hda_codec_amp_stereo(codec, line_nid, HDA_OUTPUT, 0,
10626 HDA_AMP_MUTE, mute);
10627 if (speaker_nid && speaker_nid != line_nid)
10628 snd_hda_codec_amp_stereo(codec, speaker_nid, HDA_OUTPUT, 0,
10629 HDA_AMP_MUTE, mute);
10630}
10631
10632#define alc262_hippo_master_sw_get alc262_hp_master_sw_get
10633
10634static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
10635 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai0724ea22007-08-23 00:31:43 +020010636{
10637 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
Takashi Iwai42171c12009-05-08 14:11:43 +020010638 struct alc_spec *spec = codec->spec;
10639 int val = !!*ucontrol->value.integer.value;
Takashi Iwai0724ea22007-08-23 00:31:43 +020010640
Takashi Iwai42171c12009-05-08 14:11:43 +020010641 if (val == spec->master_sw)
10642 return 0;
10643 spec->master_sw = val;
10644 alc262_hippo_master_update(codec);
10645 return 1;
Takashi Iwai0724ea22007-08-23 00:31:43 +020010646}
Takashi Iwai5b319542007-07-26 11:49:22 +020010647
Takashi Iwai42171c12009-05-08 14:11:43 +020010648#define ALC262_HIPPO_MASTER_SWITCH \
10649 { \
10650 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
10651 .name = "Master Playback Switch", \
10652 .info = snd_ctl_boolean_mono_info, \
10653 .get = alc262_hippo_master_sw_get, \
10654 .put = alc262_hippo_master_sw_put, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010010655 }, \
10656 { \
10657 .iface = NID_MAPPING, \
10658 .name = "Master Playback Switch", \
10659 .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
10660 (SUBDEV_SPEAKER(0) << 16), \
Takashi Iwai42171c12009-05-08 14:11:43 +020010661 }
10662
10663static struct snd_kcontrol_new alc262_hippo_mixer[] = {
10664 ALC262_HIPPO_MASTER_SWITCH,
10665 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10666 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10667 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10668 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10669 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10670 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10671 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10672 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10673 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10674 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10675 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
10676 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
10677 { } /* end */
10678};
10679
10680static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
10681 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10682 ALC262_HIPPO_MASTER_SWITCH,
10683 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10684 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10685 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10686 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10687 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10688 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10689 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10690 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10691 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10692 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
10693 { } /* end */
10694};
10695
10696/* mute/unmute internal speaker according to the hp jack and mute state */
10697static void alc262_hippo_automute(struct hda_codec *codec)
10698{
10699 struct alc_spec *spec = codec->spec;
10700 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai42171c12009-05-08 14:11:43 +020010701
Wu Fengguang864f92b2009-11-18 12:38:02 +080010702 spec->jack_present = snd_hda_jack_detect(codec, hp_nid);
Takashi Iwai42171c12009-05-08 14:11:43 +020010703 alc262_hippo_master_update(codec);
10704}
10705
10706static void alc262_hippo_unsol_event(struct hda_codec *codec, unsigned int res)
10707{
10708 if ((res >> 26) != ALC880_HP_EVENT)
10709 return;
10710 alc262_hippo_automute(codec);
10711}
10712
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010713static void alc262_hippo_setup(struct hda_codec *codec)
Takashi Iwai42171c12009-05-08 14:11:43 +020010714{
10715 struct alc_spec *spec = codec->spec;
10716
10717 spec->autocfg.hp_pins[0] = 0x15;
10718 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai42171c12009-05-08 14:11:43 +020010719}
10720
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010721static void alc262_hippo1_setup(struct hda_codec *codec)
Takashi Iwai42171c12009-05-08 14:11:43 +020010722{
10723 struct alc_spec *spec = codec->spec;
10724
10725 spec->autocfg.hp_pins[0] = 0x1b;
10726 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai42171c12009-05-08 14:11:43 +020010727}
10728
10729
Kailang Yang272a5272007-05-14 11:00:38 +020010730static struct snd_kcontrol_new alc262_sony_mixer[] = {
Takashi Iwai0724ea22007-08-23 00:31:43 +020010731 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai42171c12009-05-08 14:11:43 +020010732 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang272a5272007-05-14 11:00:38 +020010733 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10734 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10735 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10736 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10737 { } /* end */
10738};
10739
Kailang Yang83c34212007-07-05 11:43:05 +020010740static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020010741 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10742 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang83c34212007-07-05 11:43:05 +020010743 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10744 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10745 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10746 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10747 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10748 { } /* end */
10749};
Kailang Yang272a5272007-05-14 11:00:38 +020010750
Tony Vroonba340e82009-02-02 19:01:30 +000010751static struct snd_kcontrol_new alc262_tyan_mixer[] = {
10752 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10753 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
10754 HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
10755 HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
10756 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10757 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10758 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10759 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10760 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10761 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10762 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
10763 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
10764 { } /* end */
10765};
10766
10767static struct hda_verb alc262_tyan_verbs[] = {
10768 /* Headphone automute */
10769 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
10770 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10771 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
10772
10773 /* P11 AUX_IN, white 4-pin connector */
10774 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10775 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
10776 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
10777 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
10778
10779 {}
10780};
10781
10782/* unsolicited event for HP jack sensing */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010783static void alc262_tyan_setup(struct hda_codec *codec)
Tony Vroonba340e82009-02-02 19:01:30 +000010784{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010785 struct alc_spec *spec = codec->spec;
Tony Vroonba340e82009-02-02 19:01:30 +000010786
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010787 spec->autocfg.hp_pins[0] = 0x1b;
10788 spec->autocfg.speaker_pins[0] = 0x15;
Tony Vroonba340e82009-02-02 19:01:30 +000010789}
10790
Tony Vroonba340e82009-02-02 19:01:30 +000010791
Kailang Yangdf694da2005-12-05 19:42:22 +010010792#define alc262_capture_mixer alc882_capture_mixer
10793#define alc262_capture_alt_mixer alc882_capture_alt_mixer
10794
10795/*
10796 * generic initialization of ADC, input mixers and output mixers
10797 */
10798static struct hda_verb alc262_init_verbs[] = {
10799 /*
10800 * Unmute ADC0-2 and set the default input to mic-in
10801 */
10802 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
10803 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10804 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
10805 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10806 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
10807 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10808
Takashi Iwaicb53c622007-08-10 17:21:45 +020010809 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangdf694da2005-12-05 19:42:22 +010010810 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010811 * Note: PASD motherboards uses the Line In 2 as the input for
10812 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +010010813 */
10814 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020010815 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
10816 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
10817 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
10818 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
10819 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +010010820
10821 /*
10822 * Set up output mixers (0x0c - 0x0e)
10823 */
10824 /* set vol=0 to output mixers */
10825 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10826 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10827 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
10828 /* set up input amps for analog loopback */
10829 /* Amp Indices: DAC = 0, mixer = 1 */
10830 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10831 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10832 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10833 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10834 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
10835 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10836
10837 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
10838 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
10839 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
10840 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
10841 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10842 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
10843
10844 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
10845 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
10846 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
10847 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
10848 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Kailang Yangea1fb292008-08-26 12:58:38 +020010849
Kailang Yangdf694da2005-12-05 19:42:22 +010010850 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
10851 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
Kailang Yangea1fb292008-08-26 12:58:38 +020010852
Kailang Yangdf694da2005-12-05 19:42:22 +010010853 /* FIXME: use matrix-type input source selection */
10854 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
10855 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
10856 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
10857 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
10858 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
10859 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
10860 /* Input mixer2 */
10861 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
10862 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
10863 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
10864 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
10865 /* Input mixer3 */
10866 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
10867 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
10868 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010869 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
Kailang Yangdf694da2005-12-05 19:42:22 +010010870
10871 { }
10872};
10873
Kailang Yang4e555fe2008-08-26 13:05:55 +020010874static struct hda_verb alc262_eapd_verbs[] = {
10875 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
10876 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
10877 { }
10878};
10879
Kailang Yangccc656c2006-10-17 12:32:26 +020010880static struct hda_verb alc262_hippo1_unsol_verbs[] = {
10881 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
10882 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
10883 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
10884
10885 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
10886 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10887 {}
10888};
10889
Kailang Yang272a5272007-05-14 11:00:38 +020010890static struct hda_verb alc262_sony_unsol_verbs[] = {
10891 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
10892 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
10893 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
10894
10895 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
10896 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Akio Idehara7b1e8792008-06-09 22:46:07 +090010897 {}
Kailang Yang272a5272007-05-14 11:00:38 +020010898};
10899
Kailang Yang4e555fe2008-08-26 13:05:55 +020010900static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
10901 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10902 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
10903 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10904 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10905 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yang4e555fe2008-08-26 13:05:55 +020010906 { } /* end */
10907};
10908
10909static struct hda_verb alc262_toshiba_s06_verbs[] = {
10910 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
10911 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10912 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10913 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
10914 {0x22, AC_VERB_SET_CONNECT_SEL, 0x09},
10915 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
10916 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
10917 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
10918 {}
10919};
10920
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010921static void alc262_toshiba_s06_setup(struct hda_codec *codec)
Kailang Yang4e555fe2008-08-26 13:05:55 +020010922{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010923 struct alc_spec *spec = codec->spec;
10924
10925 spec->autocfg.hp_pins[0] = 0x15;
10926 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010927 spec->ext_mic.pin = 0x18;
10928 spec->ext_mic.mux_idx = 0;
10929 spec->int_mic.pin = 0x12;
10930 spec->int_mic.mux_idx = 9;
10931 spec->auto_mic = 1;
Kailang Yang4e555fe2008-08-26 13:05:55 +020010932}
10933
Takashi Iwai834be882006-03-01 14:16:17 +010010934/*
Pascal Terjane8f9ae22008-08-04 14:36:05 +020010935 * nec model
10936 * 0x15 = headphone
10937 * 0x16 = internal speaker
10938 * 0x18 = external mic
10939 */
10940
10941static struct snd_kcontrol_new alc262_nec_mixer[] = {
10942 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
10943 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
10944
10945 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10946 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
10947 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
10948
10949 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
10950 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10951 { } /* end */
10952};
10953
10954static struct hda_verb alc262_nec_verbs[] = {
10955 /* Unmute Speaker */
10956 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
10957
10958 /* Headphone */
10959 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
10960 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
10961
10962 /* External mic to headphone */
10963 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10964 /* External mic to speaker */
10965 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
10966 {}
10967};
10968
10969/*
Takashi Iwai834be882006-03-01 14:16:17 +010010970 * fujitsu model
Tony Vroon5d9fab22008-03-14 17:09:18 +010010971 * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
10972 * 0x1b = port replicator headphone out
Takashi Iwai834be882006-03-01 14:16:17 +010010973 */
10974
10975#define ALC_HP_EVENT 0x37
10976
10977static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
10978 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
10979 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Tony Vroon5d9fab22008-03-14 17:09:18 +010010980 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
10981 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai834be882006-03-01 14:16:17 +010010982 {}
10983};
10984
Jiang zhe0e31daf2008-03-20 12:12:39 +010010985static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
10986 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
10987 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
10988 {}
10989};
10990
Daniel T Chene2595322009-12-19 18:19:02 -050010991static struct hda_verb alc262_lenovo_3000_init_verbs[] = {
10992 /* Front Mic pin: input vref at 50% */
10993 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
10994 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
10995 {}
10996};
10997
Takashi Iwai834be882006-03-01 14:16:17 +010010998static struct hda_input_mux alc262_fujitsu_capture_source = {
Takashi Iwai39d3ed32007-10-12 15:03:48 +020010999 .num_items = 3,
Takashi Iwai834be882006-03-01 14:16:17 +010011000 .items = {
11001 { "Mic", 0x0 },
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011002 { "Int Mic", 0x1 },
Takashi Iwai834be882006-03-01 14:16:17 +010011003 { "CD", 0x4 },
11004 },
11005};
11006
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011007static struct hda_input_mux alc262_HP_capture_source = {
11008 .num_items = 5,
11009 .items = {
11010 { "Mic", 0x0 },
zhejiangaccbe492007-08-31 12:36:05 +020011011 { "Front Mic", 0x1 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011012 { "Line", 0x2 },
11013 { "CD", 0x4 },
11014 { "AUX IN", 0x6 },
11015 },
11016};
11017
zhejiangaccbe492007-08-31 12:36:05 +020011018static struct hda_input_mux alc262_HP_D7000_capture_source = {
11019 .num_items = 4,
11020 .items = {
11021 { "Mic", 0x0 },
11022 { "Front Mic", 0x2 },
11023 { "Line", 0x1 },
11024 { "CD", 0x4 },
11025 },
11026};
11027
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011028/* mute/unmute internal speaker according to the hp jacks and mute state */
Takashi Iwai834be882006-03-01 14:16:17 +010011029static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
11030{
11031 struct alc_spec *spec = codec->spec;
11032 unsigned int mute;
11033
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011034 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011035 spec->jack_present = snd_hda_jack_detect(codec, 0x14) ||
11036 snd_hda_jack_detect(codec, 0x1b);
Takashi Iwai834be882006-03-01 14:16:17 +010011037 spec->sense_updated = 1;
11038 }
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011039 /* unmute internal speaker only if both HPs are unplugged and
11040 * master switch is on
11041 */
11042 if (spec->jack_present)
11043 mute = HDA_AMP_MUTE;
11044 else
Takashi Iwai834be882006-03-01 14:16:17 +010011045 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011046 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
11047 HDA_AMP_MUTE, mute);
Takashi Iwai834be882006-03-01 14:16:17 +010011048}
11049
11050/* unsolicited event for HP jack sensing */
11051static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
11052 unsigned int res)
11053{
11054 if ((res >> 26) != ALC_HP_EVENT)
11055 return;
11056 alc262_fujitsu_automute(codec, 1);
11057}
11058
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011059static void alc262_fujitsu_init_hook(struct hda_codec *codec)
11060{
11061 alc262_fujitsu_automute(codec, 1);
11062}
11063
Takashi Iwai834be882006-03-01 14:16:17 +010011064/* bind volumes of both NID 0x0c and 0x0d */
Takashi Iwaicca3b372007-08-10 17:12:15 +020011065static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
11066 .ops = &snd_hda_bind_vol,
11067 .values = {
11068 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
11069 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
11070 0
11071 },
11072};
Takashi Iwai834be882006-03-01 14:16:17 +010011073
Jiang zhe0e31daf2008-03-20 12:12:39 +010011074/* mute/unmute internal speaker according to the hp jack and mute state */
11075static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
11076{
11077 struct alc_spec *spec = codec->spec;
11078 unsigned int mute;
11079
11080 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011081 spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
Jiang zhe0e31daf2008-03-20 12:12:39 +010011082 spec->sense_updated = 1;
11083 }
11084 if (spec->jack_present) {
11085 /* mute internal speaker */
11086 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11087 HDA_AMP_MUTE, HDA_AMP_MUTE);
11088 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
11089 HDA_AMP_MUTE, HDA_AMP_MUTE);
11090 } else {
11091 /* unmute internal speaker if necessary */
11092 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
11093 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11094 HDA_AMP_MUTE, mute);
11095 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
11096 HDA_AMP_MUTE, mute);
11097 }
11098}
11099
11100/* unsolicited event for HP jack sensing */
11101static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
11102 unsigned int res)
11103{
11104 if ((res >> 26) != ALC_HP_EVENT)
11105 return;
11106 alc262_lenovo_3000_automute(codec, 1);
11107}
11108
Takashi Iwai8de56b72009-07-24 16:51:47 +020011109static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
11110 int dir, int idx, long *valp)
11111{
11112 int i, change = 0;
11113
11114 for (i = 0; i < 2; i++, valp++)
11115 change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
11116 HDA_AMP_MUTE,
11117 *valp ? 0 : HDA_AMP_MUTE);
11118 return change;
11119}
11120
Takashi Iwai834be882006-03-01 14:16:17 +010011121/* bind hp and internal speaker mute (with plug check) */
11122static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
11123 struct snd_ctl_elem_value *ucontrol)
11124{
11125 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11126 long *valp = ucontrol->value.integer.value;
11127 int change;
11128
Takashi Iwai8de56b72009-07-24 16:51:47 +020011129 change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
11130 change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
Takashi Iwai82beb8f2007-08-10 17:09:26 +020011131 if (change)
11132 alc262_fujitsu_automute(codec, 0);
Takashi Iwai834be882006-03-01 14:16:17 +010011133 return change;
11134}
11135
11136static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
Takashi Iwaicca3b372007-08-10 17:12:15 +020011137 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
Takashi Iwai834be882006-03-01 14:16:17 +010011138 {
11139 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11140 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010011141 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwai834be882006-03-01 14:16:17 +010011142 .info = snd_hda_mixer_amp_switch_info,
11143 .get = snd_hda_mixer_amp_switch_get,
11144 .put = alc262_fujitsu_master_sw_put,
11145 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
11146 },
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010011147 {
11148 .iface = NID_MAPPING,
11149 .name = "Master Playback Switch",
11150 .private_value = 0x1b,
11151 },
Takashi Iwai834be882006-03-01 14:16:17 +010011152 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11153 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11154 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11155 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11156 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011157 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
11158 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
11159 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai834be882006-03-01 14:16:17 +010011160 { } /* end */
11161};
11162
Jiang zhe0e31daf2008-03-20 12:12:39 +010011163/* bind hp and internal speaker mute (with plug check) */
11164static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
11165 struct snd_ctl_elem_value *ucontrol)
11166{
11167 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11168 long *valp = ucontrol->value.integer.value;
11169 int change;
11170
Takashi Iwai8de56b72009-07-24 16:51:47 +020011171 change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
Jiang zhe0e31daf2008-03-20 12:12:39 +010011172 if (change)
11173 alc262_lenovo_3000_automute(codec, 0);
11174 return change;
11175}
11176
11177static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
11178 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
11179 {
11180 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11181 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010011182 .subdevice = HDA_SUBDEV_AMP_FLAG,
Jiang zhe0e31daf2008-03-20 12:12:39 +010011183 .info = snd_hda_mixer_amp_switch_info,
11184 .get = snd_hda_mixer_amp_switch_get,
11185 .put = alc262_lenovo_3000_master_sw_put,
11186 .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
11187 },
11188 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11189 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11190 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11191 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11192 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11193 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
11194 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
11195 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
11196 { } /* end */
11197};
11198
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011199static struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
11200 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
Takashi Iwai42171c12009-05-08 14:11:43 +020011201 ALC262_HIPPO_MASTER_SWITCH,
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011202 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11203 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11204 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11205 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11206 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11207 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
11208 { } /* end */
11209};
11210
Takashi Iwai304dcaa2006-07-25 14:51:16 +020011211/* additional init verbs for Benq laptops */
11212static struct hda_verb alc262_EAPD_verbs[] = {
11213 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
11214 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
11215 {}
11216};
11217
Kailang Yang83c34212007-07-05 11:43:05 +020011218static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
11219 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11220 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11221
11222 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
11223 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
11224 {}
11225};
11226
Tobin Davisf651b502007-10-26 12:40:47 +020011227/* Samsung Q1 Ultra Vista model setup */
11228static struct snd_kcontrol_new alc262_ultra_mixer[] = {
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011229 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11230 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davisf651b502007-10-26 12:40:47 +020011231 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11232 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11233 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011234 HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT),
Tobin Davisf651b502007-10-26 12:40:47 +020011235 { } /* end */
11236};
11237
11238static struct hda_verb alc262_ultra_verbs[] = {
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011239 /* output mixer */
11240 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11241 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11242 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11243 /* speaker */
11244 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11245 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11246 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11247 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
11248 /* HP */
Tobin Davisf651b502007-10-26 12:40:47 +020011249 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011250 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11251 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11252 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11253 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11254 /* internal mic */
11255 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
11256 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11257 /* ADC, choose mic */
11258 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11259 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11260 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11261 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11262 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11263 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11264 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
11265 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
11266 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
11267 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
Tobin Davisf651b502007-10-26 12:40:47 +020011268 {}
11269};
11270
Tobin Davisf651b502007-10-26 12:40:47 +020011271/* mute/unmute internal speaker according to the hp jack and mute state */
11272static void alc262_ultra_automute(struct hda_codec *codec)
11273{
11274 struct alc_spec *spec = codec->spec;
11275 unsigned int mute;
Tobin Davisf651b502007-10-26 12:40:47 +020011276
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011277 mute = 0;
11278 /* auto-mute only when HP is used as HP */
11279 if (!spec->cur_mux[0]) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011280 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011281 if (spec->jack_present)
11282 mute = HDA_AMP_MUTE;
Tobin Davisf651b502007-10-26 12:40:47 +020011283 }
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011284 /* mute/unmute internal speaker */
11285 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11286 HDA_AMP_MUTE, mute);
11287 /* mute/unmute HP */
11288 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
11289 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
Tobin Davisf651b502007-10-26 12:40:47 +020011290}
11291
11292/* unsolicited event for HP jack sensing */
11293static void alc262_ultra_unsol_event(struct hda_codec *codec,
11294 unsigned int res)
11295{
11296 if ((res >> 26) != ALC880_HP_EVENT)
11297 return;
11298 alc262_ultra_automute(codec);
11299}
11300
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011301static struct hda_input_mux alc262_ultra_capture_source = {
11302 .num_items = 2,
11303 .items = {
11304 { "Mic", 0x1 },
11305 { "Headphone", 0x7 },
11306 },
11307};
11308
11309static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
11310 struct snd_ctl_elem_value *ucontrol)
11311{
11312 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11313 struct alc_spec *spec = codec->spec;
11314 int ret;
11315
Takashi Iwai54cbc9a2008-10-31 15:24:04 +010011316 ret = alc_mux_enum_put(kcontrol, ucontrol);
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011317 if (!ret)
11318 return 0;
11319 /* reprogram the HP pin as mic or HP according to the input source */
11320 snd_hda_codec_write_cache(codec, 0x15, 0,
11321 AC_VERB_SET_PIN_WIDGET_CONTROL,
11322 spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
11323 alc262_ultra_automute(codec); /* mute/unmute HP */
11324 return ret;
11325}
11326
11327static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
11328 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
11329 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
11330 {
11331 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11332 .name = "Capture Source",
Takashi Iwai54cbc9a2008-10-31 15:24:04 +010011333 .info = alc_mux_enum_info,
11334 .get = alc_mux_enum_get,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011335 .put = alc262_ultra_mux_enum_put,
11336 },
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010011337 {
11338 .iface = NID_MAPPING,
11339 .name = "Capture Source",
11340 .private_value = 0x15,
11341 },
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011342 { } /* end */
11343};
11344
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011345/* We use two mixers depending on the output pin; 0x16 is a mono output
11346 * and thus it's bound with a different mixer.
11347 * This function returns which mixer amp should be used.
11348 */
11349static int alc262_check_volbit(hda_nid_t nid)
11350{
11351 if (!nid)
11352 return 0;
11353 else if (nid == 0x16)
11354 return 2;
11355 else
11356 return 1;
11357}
11358
11359static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
11360 const char *pfx, int *vbits)
11361{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011362 unsigned long val;
11363 int vbit;
11364
11365 vbit = alc262_check_volbit(nid);
11366 if (!vbit)
11367 return 0;
11368 if (*vbits & vbit) /* a volume control for this mixer already there */
11369 return 0;
11370 *vbits |= vbit;
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011371 if (vbit == 2)
11372 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
11373 else
11374 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
Takashi Iwai0afe5f82009-10-02 09:20:00 +020011375 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val);
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011376}
11377
11378static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
11379 const char *pfx)
11380{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011381 unsigned long val;
11382
11383 if (!nid)
11384 return 0;
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011385 if (nid == 0x16)
11386 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
11387 else
11388 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
Takashi Iwai0afe5f82009-10-02 09:20:00 +020011389 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val);
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011390}
11391
Kailang Yangdf694da2005-12-05 19:42:22 +010011392/* add playback controls from the parsed DAC table */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011393static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
11394 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010011395{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011396 const char *pfx;
11397 int vbits;
Kailang Yangdf694da2005-12-05 19:42:22 +010011398 int err;
11399
11400 spec->multiout.num_dacs = 1; /* only use one dac */
11401 spec->multiout.dac_nids = spec->private_dac_nids;
11402 spec->multiout.dac_nids[0] = 2;
11403
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011404 if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
11405 pfx = "Master";
11406 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
11407 pfx = "Speaker";
11408 else
11409 pfx = "Front";
11410 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx);
11411 if (err < 0)
11412 return err;
11413 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker");
11414 if (err < 0)
11415 return err;
11416 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone");
11417 if (err < 0)
11418 return err;
Kailang Yangdf694da2005-12-05 19:42:22 +010011419
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011420 vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
11421 alc262_check_volbit(cfg->speaker_pins[0]) |
11422 alc262_check_volbit(cfg->hp_pins[0]);
11423 if (vbits == 1 || vbits == 2)
11424 pfx = "Master"; /* only one mixer is used */
11425 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
11426 pfx = "Speaker";
11427 else
11428 pfx = "Front";
11429 vbits = 0;
11430 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits);
11431 if (err < 0)
11432 return err;
11433 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker",
11434 &vbits);
11435 if (err < 0)
11436 return err;
11437 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone",
11438 &vbits);
11439 if (err < 0)
11440 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011441 return 0;
Kailang Yangdf694da2005-12-05 19:42:22 +010011442}
11443
Takashi Iwai05f5f472009-08-25 13:10:18 +020011444#define alc262_auto_create_input_ctls \
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +010011445 alc882_auto_create_input_ctls
Kailang Yangdf694da2005-12-05 19:42:22 +010011446
11447/*
11448 * generic initialization of ADC, input mixers and output mixers
11449 */
11450static struct hda_verb alc262_volume_init_verbs[] = {
11451 /*
11452 * Unmute ADC0-2 and set the default input to mic-in
11453 */
11454 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11455 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11456 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11457 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11458 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11459 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11460
Takashi Iwaicb53c622007-08-10 17:21:45 +020011461 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangdf694da2005-12-05 19:42:22 +010011462 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011463 * Note: PASD motherboards uses the Line In 2 as the input for
11464 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +010011465 */
11466 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011467 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11468 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11469 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11470 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11471 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +010011472
11473 /*
11474 * Set up output mixers (0x0c - 0x0f)
11475 */
11476 /* set vol=0 to output mixers */
11477 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11478 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11479 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yangea1fb292008-08-26 12:58:38 +020011480
Kailang Yangdf694da2005-12-05 19:42:22 +010011481 /* set up input amps for analog loopback */
11482 /* Amp Indices: DAC = 0, mixer = 1 */
11483 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11484 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11485 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11486 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11487 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11488 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11489
11490 /* FIXME: use matrix-type input source selection */
11491 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11492 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11493 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11494 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11495 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11496 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11497 /* Input mixer2 */
11498 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11499 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11500 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11501 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11502 /* Input mixer3 */
11503 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11504 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11505 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11506 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11507
11508 { }
11509};
11510
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011511static struct hda_verb alc262_HP_BPC_init_verbs[] = {
11512 /*
11513 * Unmute ADC0-2 and set the default input to mic-in
11514 */
11515 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11516 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11517 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11518 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11519 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11520 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11521
Takashi Iwaicb53c622007-08-10 17:21:45 +020011522 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011523 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011524 * Note: PASD motherboards uses the Line In 2 as the input for
11525 * front panel mic (mic 2)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011526 */
11527 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011528 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11529 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11530 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11531 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11532 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11533 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
11534 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
Kailang Yangea1fb292008-08-26 12:58:38 +020011535
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011536 /*
11537 * Set up output mixers (0x0c - 0x0e)
11538 */
11539 /* set vol=0 to output mixers */
11540 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11541 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11542 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11543
11544 /* set up input amps for analog loopback */
11545 /* Amp Indices: DAC = 0, mixer = 1 */
11546 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11547 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11548 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11549 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11550 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11551 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11552
Takashi Iwaice875f02008-01-28 18:17:43 +010011553 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011554 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
11555 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
11556
11557 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11558 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11559
11560 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11561 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11562
11563 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11564 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11565 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11566 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11567 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11568
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011569 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011570 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11571 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011572 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011573 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11574 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11575
11576
11577 /* FIXME: use matrix-type input source selection */
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011578 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 0b, 12 */
11579 /* Input mixer1: only unmute Mic */
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011580 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011581 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
11582 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11583 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11584 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11585 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
11586 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
11587 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
11588 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011589 /* Input mixer2 */
11590 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011591 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
11592 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11593 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11594 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11595 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
11596 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
11597 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
11598 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011599 /* Input mixer3 */
11600 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020011601 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
11602 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11603 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11604 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11605 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
11606 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
11607 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
11608 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011609
Takashi Iwaice875f02008-01-28 18:17:43 +010011610 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
11611
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011612 { }
11613};
11614
Kailang Yangcd7509a2007-01-26 18:33:17 +010011615static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
11616 /*
11617 * Unmute ADC0-2 and set the default input to mic-in
11618 */
11619 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11620 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11621 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11622 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11623 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11624 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11625
Takashi Iwaicb53c622007-08-10 17:21:45 +020011626 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangcd7509a2007-01-26 18:33:17 +010011627 * mixer widget
11628 * Note: PASD motherboards uses the Line In 2 as the input for front
11629 * panel mic (mic 2)
11630 */
11631 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011632 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11633 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11634 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11635 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11636 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11637 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
11638 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
11639 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Kailang Yangcd7509a2007-01-26 18:33:17 +010011640 /*
11641 * Set up output mixers (0x0c - 0x0e)
11642 */
11643 /* set vol=0 to output mixers */
11644 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11645 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11646 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11647
11648 /* set up input amps for analog loopback */
11649 /* Amp Indices: DAC = 0, mixer = 1 */
11650 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11651 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11652 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11653 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11654 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11655 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11656
11657
11658 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */
11659 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */
11660 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */
11661 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */
11662 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
11663 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */
11664 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */
11665
11666 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11667 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11668
11669 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11670 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
11671
11672 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
11673 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11674 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11675 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
11676 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11677 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
11678
11679 /* FIXME: use matrix-type input source selection */
11680 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11681 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11682 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
11683 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
11684 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
11685 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
11686 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
11687 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
11688 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
11689 /* Input mixer2 */
11690 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11691 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11692 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
11693 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
11694 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
11695 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
11696 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
11697 /* Input mixer3 */
11698 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11699 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11700 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
11701 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
11702 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
11703 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
11704 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
11705
Takashi Iwaice875f02008-01-28 18:17:43 +010011706 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
11707
Kailang Yangcd7509a2007-01-26 18:33:17 +010011708 { }
11709};
11710
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011711static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
11712
11713 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Front Speaker */
11714 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
11715 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
11716
11717 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* MIC jack */
11718 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
11719 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
11720 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
11721
11722 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP jack */
11723 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11724 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11725 {}
11726};
11727
11728
Takashi Iwaicb53c622007-08-10 17:21:45 +020011729#ifdef CONFIG_SND_HDA_POWER_SAVE
11730#define alc262_loopbacks alc880_loopbacks
11731#endif
11732
Sasha Alexandrdef319f2009-06-16 16:00:15 -040011733/* pcm configuration: identical with ALC880 */
Kailang Yangdf694da2005-12-05 19:42:22 +010011734#define alc262_pcm_analog_playback alc880_pcm_analog_playback
11735#define alc262_pcm_analog_capture alc880_pcm_analog_capture
11736#define alc262_pcm_digital_playback alc880_pcm_digital_playback
11737#define alc262_pcm_digital_capture alc880_pcm_digital_capture
11738
11739/*
11740 * BIOS auto configuration
11741 */
11742static int alc262_parse_auto_config(struct hda_codec *codec)
11743{
11744 struct alc_spec *spec = codec->spec;
11745 int err;
11746 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
11747
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011748 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
11749 alc262_ignore);
11750 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010011751 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011752 if (!spec->autocfg.line_outs) {
Takashi Iwai0852d7a2009-02-11 11:35:15 +010011753 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011754 spec->multiout.max_channels = 2;
11755 spec->no_analog = 1;
11756 goto dig_only;
11757 }
Kailang Yangdf694da2005-12-05 19:42:22 +010011758 return 0; /* can't find valid BIOS pin config */
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011759 }
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011760 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
11761 if (err < 0)
11762 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020011763 err = alc262_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011764 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010011765 return err;
11766
11767 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
11768
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011769 dig_only:
Takashi Iwai0852d7a2009-02-11 11:35:15 +010011770 if (spec->autocfg.dig_outs) {
Kailang Yangdf694da2005-12-05 19:42:22 +010011771 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
Takashi Iwai0852d7a2009-02-11 11:35:15 +010011772 spec->dig_out_type = spec->autocfg.dig_out_type[0];
Takashi Iwaie64f14f2009-01-20 18:32:55 +010011773 }
Kailang Yangdf694da2005-12-05 19:42:22 +010011774 if (spec->autocfg.dig_in_pin)
11775 spec->dig_in_nid = ALC262_DIGIN_NID;
11776
Takashi Iwai603c4012008-07-30 15:01:44 +020011777 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010011778 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +010011779
Takashi Iwaid88897e2008-10-31 15:01:37 +010011780 add_verb(spec, alc262_volume_init_verbs);
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +020011781 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020011782 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +010011783
Takashi Iwai776e1842007-08-29 15:07:11 +020011784 err = alc_auto_add_mic_boost(codec);
11785 if (err < 0)
11786 return err;
11787
Kailang Yang6227cdc2010-02-25 08:36:52 +010011788 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020011789
Kailang Yangdf694da2005-12-05 19:42:22 +010011790 return 1;
11791}
11792
11793#define alc262_auto_init_multi_out alc882_auto_init_multi_out
11794#define alc262_auto_init_hp_out alc882_auto_init_hp_out
11795#define alc262_auto_init_analog_input alc882_auto_init_analog_input
Takashi Iwaif511b012008-08-15 16:46:42 +020011796#define alc262_auto_init_input_src alc882_auto_init_input_src
Kailang Yangdf694da2005-12-05 19:42:22 +010011797
11798
11799/* init callback for auto-configuration model -- overriding the default init */
Takashi Iwaiae6b8132006-03-03 16:47:17 +010011800static void alc262_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +010011801{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010011802 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010011803 alc262_auto_init_multi_out(codec);
11804 alc262_auto_init_hp_out(codec);
11805 alc262_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020011806 alc262_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010011807 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020011808 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010011809}
11810
11811/*
11812 * configuration and preset
11813 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011814static const char *alc262_models[ALC262_MODEL_LAST] = {
11815 [ALC262_BASIC] = "basic",
11816 [ALC262_HIPPO] = "hippo",
11817 [ALC262_HIPPO_1] = "hippo_1",
11818 [ALC262_FUJITSU] = "fujitsu",
11819 [ALC262_HP_BPC] = "hp-bpc",
Kailang Yangcd7509a2007-01-26 18:33:17 +010011820 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
Takashi Iwai61dc35d2007-11-14 12:26:44 +010011821 [ALC262_HP_TC_T5735] = "hp-tc-t5735",
Kailang Yang8c427222008-01-10 13:03:59 +010011822 [ALC262_HP_RP5700] = "hp-rp5700",
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011823 [ALC262_BENQ_ED8] = "benq",
Takashi Iwai0f405022007-07-06 12:24:11 +020011824 [ALC262_BENQ_T31] = "benq-t31",
11825 [ALC262_SONY_ASSAMD] = "sony-assamd",
Takashi Iwai2922c9a2008-08-27 18:12:42 +020011826 [ALC262_TOSHIBA_S06] = "toshiba-s06",
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011827 [ALC262_TOSHIBA_RX1] = "toshiba-rx1",
Tobin Davisf651b502007-10-26 12:40:47 +020011828 [ALC262_ULTRA] = "ultra",
Jiang zhe0e31daf2008-03-20 12:12:39 +010011829 [ALC262_LENOVO_3000] = "lenovo-3000",
Pascal Terjane8f9ae22008-08-04 14:36:05 +020011830 [ALC262_NEC] = "nec",
Tony Vroonba340e82009-02-02 19:01:30 +000011831 [ALC262_TYAN] = "tyan",
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011832 [ALC262_AUTO] = "auto",
11833};
11834
11835static struct snd_pci_quirk alc262_cfg_tbl[] = {
11836 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
Pascal Terjane8f9ae22008-08-04 14:36:05 +020011837 SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
Takashi Iwaidea0a502009-02-09 17:14:52 +010011838 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
11839 ALC262_HP_BPC),
11840 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
11841 ALC262_HP_BPC),
Takashi Iwai53eff7e2009-02-27 17:49:44 +010011842 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
11843 ALC262_HP_BPC),
Kailang Yangcd7509a2007-01-26 18:33:17 +010011844 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010011845 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010011846 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010011847 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010011848 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010011849 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010011850 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010011851 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010011852 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
11853 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
11854 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011855 SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
11856 ALC262_HP_TC_T5735),
Kailang Yang8c427222008-01-10 13:03:59 +010011857 SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010011858 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011859 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010011860 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
Takashi Iwaibd6afe32009-03-04 11:30:25 +010011861 SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
Takashi Iwai376b5082009-06-22 11:03:13 +020011862 SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
Daniel T Chen95491d92009-11-08 19:03:55 -050011863 SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
Takashi Iwai12929ba2009-11-17 15:58:35 +010011864 SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
Takashi Iwaic5b51652009-11-17 16:01:58 +010011865#if 0 /* disable the quirk since model=auto works better in recent versions */
Takashi Iwaif872a912009-02-26 00:57:01 +010011866 SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
11867 ALC262_SONY_ASSAMD),
Takashi Iwaic5b51652009-11-17 16:01:58 +010011868#endif
Akio Idehara36ca6e12008-06-09 22:57:40 +090011869 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011870 ALC262_TOSHIBA_RX1),
Kailang Yang80ffe862008-10-15 11:23:27 +020011871 SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011872 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
Tony Vroon3f1eeae2008-02-25 16:44:13 +010011873 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
Tony Vroonba340e82009-02-02 19:01:30 +000011874 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
Takashi Iwaidea0a502009-02-09 17:14:52 +010011875 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
11876 ALC262_ULTRA),
Luke Yelavich3e420e72008-12-16 12:37:47 +110011877 SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
Jiang zhe0e31daf2008-03-20 12:12:39 +010011878 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010011879 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
Kailang Yang83c34212007-07-05 11:43:05 +020011880 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010011881 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
Kailang Yangdf694da2005-12-05 19:42:22 +010011882 {}
11883};
11884
11885static struct alc_config_preset alc262_presets[] = {
11886 [ALC262_BASIC] = {
11887 .mixers = { alc262_base_mixer },
11888 .init_verbs = { alc262_init_verbs },
11889 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11890 .dac_nids = alc262_dac_nids,
11891 .hp_nid = 0x03,
11892 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11893 .channel_mode = alc262_modes,
Takashi Iwaia3bcba32005-12-06 19:05:29 +010011894 .input_mux = &alc262_capture_source,
Kailang Yangdf694da2005-12-05 19:42:22 +010011895 },
Kailang Yangccc656c2006-10-17 12:32:26 +020011896 [ALC262_HIPPO] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020011897 .mixers = { alc262_hippo_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +020011898 .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +020011899 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11900 .dac_nids = alc262_dac_nids,
11901 .hp_nid = 0x03,
11902 .dig_out_nid = ALC262_DIGOUT_NID,
11903 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11904 .channel_mode = alc262_modes,
11905 .input_mux = &alc262_capture_source,
11906 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011907 .setup = alc262_hippo_setup,
11908 .init_hook = alc262_hippo_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +020011909 },
11910 [ALC262_HIPPO_1] = {
11911 .mixers = { alc262_hippo1_mixer },
11912 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
11913 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11914 .dac_nids = alc262_dac_nids,
11915 .hp_nid = 0x02,
11916 .dig_out_nid = ALC262_DIGOUT_NID,
11917 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11918 .channel_mode = alc262_modes,
11919 .input_mux = &alc262_capture_source,
Takashi Iwai42171c12009-05-08 14:11:43 +020011920 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011921 .setup = alc262_hippo1_setup,
11922 .init_hook = alc262_hippo_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +020011923 },
Takashi Iwai834be882006-03-01 14:16:17 +010011924 [ALC262_FUJITSU] = {
11925 .mixers = { alc262_fujitsu_mixer },
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011926 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
11927 alc262_fujitsu_unsol_verbs },
Takashi Iwai834be882006-03-01 14:16:17 +010011928 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11929 .dac_nids = alc262_dac_nids,
11930 .hp_nid = 0x03,
11931 .dig_out_nid = ALC262_DIGOUT_NID,
11932 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11933 .channel_mode = alc262_modes,
11934 .input_mux = &alc262_fujitsu_capture_source,
Takashi Iwaiae6b8132006-03-03 16:47:17 +010011935 .unsol_event = alc262_fujitsu_unsol_event,
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011936 .init_hook = alc262_fujitsu_init_hook,
Takashi Iwai834be882006-03-01 14:16:17 +010011937 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011938 [ALC262_HP_BPC] = {
11939 .mixers = { alc262_HP_BPC_mixer },
11940 .init_verbs = { alc262_HP_BPC_init_verbs },
11941 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11942 .dac_nids = alc262_dac_nids,
11943 .hp_nid = 0x03,
11944 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11945 .channel_mode = alc262_modes,
11946 .input_mux = &alc262_HP_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010011947 .unsol_event = alc262_hp_bpc_unsol_event,
11948 .init_hook = alc262_hp_bpc_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011949 },
Kailang Yangcd7509a2007-01-26 18:33:17 +010011950 [ALC262_HP_BPC_D7000_WF] = {
11951 .mixers = { alc262_HP_BPC_WildWest_mixer },
11952 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
11953 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11954 .dac_nids = alc262_dac_nids,
11955 .hp_nid = 0x03,
11956 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11957 .channel_mode = alc262_modes,
zhejiangaccbe492007-08-31 12:36:05 +020011958 .input_mux = &alc262_HP_D7000_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010011959 .unsol_event = alc262_hp_wildwest_unsol_event,
11960 .init_hook = alc262_hp_wildwest_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011961 },
Kailang Yangcd7509a2007-01-26 18:33:17 +010011962 [ALC262_HP_BPC_D7000_WL] = {
11963 .mixers = { alc262_HP_BPC_WildWest_mixer,
11964 alc262_HP_BPC_WildWest_option_mixer },
11965 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
11966 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11967 .dac_nids = alc262_dac_nids,
11968 .hp_nid = 0x03,
11969 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11970 .channel_mode = alc262_modes,
zhejiangaccbe492007-08-31 12:36:05 +020011971 .input_mux = &alc262_HP_D7000_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010011972 .unsol_event = alc262_hp_wildwest_unsol_event,
11973 .init_hook = alc262_hp_wildwest_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011974 },
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011975 [ALC262_HP_TC_T5735] = {
11976 .mixers = { alc262_hp_t5735_mixer },
11977 .init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
11978 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11979 .dac_nids = alc262_dac_nids,
11980 .hp_nid = 0x03,
11981 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11982 .channel_mode = alc262_modes,
11983 .input_mux = &alc262_capture_source,
Takashi Iwaidc99be42010-01-20 08:35:06 +010011984 .unsol_event = alc_sku_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011985 .setup = alc262_hp_t5735_setup,
Takashi Iwaidc99be42010-01-20 08:35:06 +010011986 .init_hook = alc_inithook,
Kailang Yang8c427222008-01-10 13:03:59 +010011987 },
11988 [ALC262_HP_RP5700] = {
11989 .mixers = { alc262_hp_rp5700_mixer },
11990 .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
11991 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
11992 .dac_nids = alc262_dac_nids,
11993 .num_channel_mode = ARRAY_SIZE(alc262_modes),
11994 .channel_mode = alc262_modes,
11995 .input_mux = &alc262_hp_rp5700_capture_source,
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011996 },
Takashi Iwai304dcaa2006-07-25 14:51:16 +020011997 [ALC262_BENQ_ED8] = {
11998 .mixers = { alc262_base_mixer },
11999 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
12000 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12001 .dac_nids = alc262_dac_nids,
12002 .hp_nid = 0x03,
12003 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12004 .channel_mode = alc262_modes,
12005 .input_mux = &alc262_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012006 },
Kailang Yang272a5272007-05-14 11:00:38 +020012007 [ALC262_SONY_ASSAMD] = {
12008 .mixers = { alc262_sony_mixer },
12009 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
12010 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12011 .dac_nids = alc262_dac_nids,
12012 .hp_nid = 0x02,
12013 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12014 .channel_mode = alc262_modes,
12015 .input_mux = &alc262_capture_source,
12016 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012017 .setup = alc262_hippo_setup,
12018 .init_hook = alc262_hippo_automute,
Kailang Yang83c34212007-07-05 11:43:05 +020012019 },
12020 [ALC262_BENQ_T31] = {
12021 .mixers = { alc262_benq_t31_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +020012022 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
12023 alc_hp15_unsol_verbs },
Kailang Yang83c34212007-07-05 11:43:05 +020012024 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12025 .dac_nids = alc262_dac_nids,
12026 .hp_nid = 0x03,
12027 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12028 .channel_mode = alc262_modes,
12029 .input_mux = &alc262_capture_source,
12030 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012031 .setup = alc262_hippo_setup,
12032 .init_hook = alc262_hippo_automute,
Kailang Yangea1fb292008-08-26 12:58:38 +020012033 },
Tobin Davisf651b502007-10-26 12:40:47 +020012034 [ALC262_ULTRA] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010012035 .mixers = { alc262_ultra_mixer },
12036 .cap_mixer = alc262_ultra_capture_mixer,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010012037 .init_verbs = { alc262_ultra_verbs },
Tobin Davisf651b502007-10-26 12:40:47 +020012038 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12039 .dac_nids = alc262_dac_nids,
Tobin Davisf651b502007-10-26 12:40:47 +020012040 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12041 .channel_mode = alc262_modes,
12042 .input_mux = &alc262_ultra_capture_source,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010012043 .adc_nids = alc262_adc_nids, /* ADC0 */
12044 .capsrc_nids = alc262_capsrc_nids,
12045 .num_adc_nids = 1, /* single ADC */
Tobin Davisf651b502007-10-26 12:40:47 +020012046 .unsol_event = alc262_ultra_unsol_event,
12047 .init_hook = alc262_ultra_automute,
12048 },
Jiang zhe0e31daf2008-03-20 12:12:39 +010012049 [ALC262_LENOVO_3000] = {
12050 .mixers = { alc262_lenovo_3000_mixer },
12051 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
Daniel T Chene2595322009-12-19 18:19:02 -050012052 alc262_lenovo_3000_unsol_verbs,
12053 alc262_lenovo_3000_init_verbs },
Jiang zhe0e31daf2008-03-20 12:12:39 +010012054 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12055 .dac_nids = alc262_dac_nids,
12056 .hp_nid = 0x03,
12057 .dig_out_nid = ALC262_DIGOUT_NID,
12058 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12059 .channel_mode = alc262_modes,
12060 .input_mux = &alc262_fujitsu_capture_source,
12061 .unsol_event = alc262_lenovo_3000_unsol_event,
12062 },
Pascal Terjane8f9ae22008-08-04 14:36:05 +020012063 [ALC262_NEC] = {
12064 .mixers = { alc262_nec_mixer },
12065 .init_verbs = { alc262_nec_verbs },
12066 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12067 .dac_nids = alc262_dac_nids,
12068 .hp_nid = 0x03,
12069 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12070 .channel_mode = alc262_modes,
12071 .input_mux = &alc262_capture_source,
12072 },
Kailang Yang4e555fe2008-08-26 13:05:55 +020012073 [ALC262_TOSHIBA_S06] = {
12074 .mixers = { alc262_toshiba_s06_mixer },
12075 .init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
12076 alc262_eapd_verbs },
12077 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12078 .capsrc_nids = alc262_dmic_capsrc_nids,
12079 .dac_nids = alc262_dac_nids,
12080 .adc_nids = alc262_dmic_adc_nids, /* ADC0 */
Takashi Iwaiae14ef62009-06-22 08:16:56 +020012081 .num_adc_nids = 1, /* single ADC */
Kailang Yang4e555fe2008-08-26 13:05:55 +020012082 .dig_out_nid = ALC262_DIGOUT_NID,
12083 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12084 .channel_mode = alc262_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012085 .unsol_event = alc_sku_unsol_event,
12086 .setup = alc262_toshiba_s06_setup,
12087 .init_hook = alc_inithook,
Kailang Yang4e555fe2008-08-26 13:05:55 +020012088 },
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012089 [ALC262_TOSHIBA_RX1] = {
12090 .mixers = { alc262_toshiba_rx1_mixer },
12091 .init_verbs = { alc262_init_verbs, alc262_toshiba_rx1_unsol_verbs },
12092 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12093 .dac_nids = alc262_dac_nids,
12094 .hp_nid = 0x03,
12095 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12096 .channel_mode = alc262_modes,
12097 .input_mux = &alc262_capture_source,
12098 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012099 .setup = alc262_hippo_setup,
12100 .init_hook = alc262_hippo_automute,
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012101 },
Tony Vroonba340e82009-02-02 19:01:30 +000012102 [ALC262_TYAN] = {
12103 .mixers = { alc262_tyan_mixer },
12104 .init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
12105 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12106 .dac_nids = alc262_dac_nids,
12107 .hp_nid = 0x02,
12108 .dig_out_nid = ALC262_DIGOUT_NID,
12109 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12110 .channel_mode = alc262_modes,
12111 .input_mux = &alc262_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012112 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012113 .setup = alc262_tyan_setup,
12114 .init_hook = alc_automute_amp,
Tony Vroonba340e82009-02-02 19:01:30 +000012115 },
Kailang Yangdf694da2005-12-05 19:42:22 +010012116};
12117
12118static int patch_alc262(struct hda_codec *codec)
12119{
12120 struct alc_spec *spec;
12121 int board_config;
12122 int err;
12123
Robert P. J. Daydc041e02006-12-19 14:44:15 +010012124 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yangdf694da2005-12-05 19:42:22 +010012125 if (spec == NULL)
12126 return -ENOMEM;
12127
12128 codec->spec = spec;
12129#if 0
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012130 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
12131 * under-run
12132 */
Kailang Yangdf694da2005-12-05 19:42:22 +010012133 {
12134 int tmp;
12135 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
12136 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
12137 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
12138 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
12139 }
12140#endif
12141
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +020012142 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
12143
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012144 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
12145 alc262_models,
12146 alc262_cfg_tbl);
Kailang Yangcd7509a2007-01-26 18:33:17 +010012147
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012148 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020012149 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
12150 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +010012151 board_config = ALC262_AUTO;
12152 }
12153
12154 if (board_config == ALC262_AUTO) {
12155 /* automatic parse from the BIOS config */
12156 err = alc262_parse_auto_config(codec);
12157 if (err < 0) {
12158 alc_free(codec);
12159 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012160 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012161 printk(KERN_INFO
12162 "hda_codec: Cannot set up configuration "
12163 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +010012164 board_config = ALC262_BASIC;
12165 }
12166 }
12167
Takashi Iwai07eba612009-02-19 08:06:35 +010012168 if (!spec->no_analog) {
12169 err = snd_hda_attach_beep_device(codec, 0x1);
12170 if (err < 0) {
12171 alc_free(codec);
12172 return err;
12173 }
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090012174 }
12175
Kailang Yangdf694da2005-12-05 19:42:22 +010012176 if (board_config != ALC262_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020012177 setup_preset(codec, &alc262_presets[board_config]);
Kailang Yangdf694da2005-12-05 19:42:22 +010012178
Kailang Yangdf694da2005-12-05 19:42:22 +010012179 spec->stream_analog_playback = &alc262_pcm_analog_playback;
12180 spec->stream_analog_capture = &alc262_pcm_analog_capture;
Kailang Yangea1fb292008-08-26 12:58:38 +020012181
Kailang Yangdf694da2005-12-05 19:42:22 +010012182 spec->stream_digital_playback = &alc262_pcm_digital_playback;
12183 spec->stream_digital_capture = &alc262_pcm_digital_capture;
12184
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012185 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwai8c927b42009-06-22 10:56:54 +020012186 int i;
12187 /* check whether the digital-mic has to be supported */
12188 for (i = 0; i < spec->input_mux->num_items; i++) {
12189 if (spec->input_mux->items[i].index >= 9)
12190 break;
12191 }
12192 if (i < spec->input_mux->num_items) {
12193 /* use only ADC0 */
12194 spec->adc_nids = alc262_dmic_adc_nids;
12195 spec->num_adc_nids = 1;
12196 spec->capsrc_nids = alc262_dmic_capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +010012197 } else {
Takashi Iwai8c927b42009-06-22 10:56:54 +020012198 /* all analog inputs */
12199 /* check whether NID 0x07 is valid */
12200 unsigned int wcap = get_wcaps(codec, 0x07);
12201
12202 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020012203 wcap = get_wcaps_type(wcap);
Takashi Iwai8c927b42009-06-22 10:56:54 +020012204 if (wcap != AC_WID_AUD_IN) {
12205 spec->adc_nids = alc262_adc_nids_alt;
12206 spec->num_adc_nids =
12207 ARRAY_SIZE(alc262_adc_nids_alt);
12208 spec->capsrc_nids = alc262_capsrc_nids_alt;
12209 } else {
12210 spec->adc_nids = alc262_adc_nids;
12211 spec->num_adc_nids =
12212 ARRAY_SIZE(alc262_adc_nids);
12213 spec->capsrc_nids = alc262_capsrc_nids;
12214 }
Kailang Yangdf694da2005-12-05 19:42:22 +010012215 }
12216 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +010012217 if (!spec->cap_mixer && !spec->no_analog)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020012218 set_capture_mixer(codec);
Takashi Iwai07eba612009-02-19 08:06:35 +010012219 if (!spec->no_analog)
12220 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Kailang Yangdf694da2005-12-05 19:42:22 +010012221
Takashi Iwai2134ea42008-01-10 16:53:55 +010012222 spec->vmaster_nid = 0x0c;
12223
Kailang Yangdf694da2005-12-05 19:42:22 +010012224 codec->patch_ops = alc_patch_ops;
12225 if (board_config == ALC262_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +010012226 spec->init_hook = alc262_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020012227#ifdef CONFIG_SND_HDA_POWER_SAVE
12228 if (!spec->loopback.amplist)
12229 spec->loopback.amplist = alc262_loopbacks;
12230#endif
Kailang Yangea1fb292008-08-26 12:58:38 +020012231
Kailang Yangdf694da2005-12-05 19:42:22 +010012232 return 0;
12233}
12234
Kailang Yangdf694da2005-12-05 19:42:22 +010012235/*
Kailang Yanga361d842007-06-05 12:30:55 +020012236 * ALC268 channel source setting (2 channel)
12237 */
12238#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
12239#define alc268_modes alc260_modes
Kailang Yangea1fb292008-08-26 12:58:38 +020012240
Kailang Yanga361d842007-06-05 12:30:55 +020012241static hda_nid_t alc268_dac_nids[2] = {
12242 /* front, hp */
12243 0x02, 0x03
12244};
12245
12246static hda_nid_t alc268_adc_nids[2] = {
12247 /* ADC0-1 */
12248 0x08, 0x07
12249};
12250
12251static hda_nid_t alc268_adc_nids_alt[1] = {
12252 /* ADC0 */
12253 0x08
12254};
12255
Takashi Iwaie1406342008-02-11 18:32:32 +010012256static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
12257
Kailang Yanga361d842007-06-05 12:30:55 +020012258static struct snd_kcontrol_new alc268_base_mixer[] = {
12259 /* output mixer control */
12260 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12261 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12262 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12263 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwai33bf17a2007-08-21 11:51:42 +020012264 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12265 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
12266 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
Kailang Yanga361d842007-06-05 12:30:55 +020012267 { }
12268};
12269
Takashi Iwai42171c12009-05-08 14:11:43 +020012270static struct snd_kcontrol_new alc268_toshiba_mixer[] = {
12271 /* output mixer control */
12272 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12273 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12274 ALC262_HIPPO_MASTER_SWITCH,
12275 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12276 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
12277 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
12278 { }
12279};
12280
Takashi Iwaiaef9d312008-02-19 13:16:41 +010012281/* bind Beep switches of both NID 0x0f and 0x10 */
12282static struct hda_bind_ctls alc268_bind_beep_sw = {
12283 .ops = &snd_hda_bind_sw,
12284 .values = {
12285 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
12286 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
12287 0
12288 },
12289};
12290
12291static struct snd_kcontrol_new alc268_beep_mixer[] = {
12292 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
12293 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
12294 { }
12295};
12296
Kailang Yangd1a991a2007-08-15 16:21:59 +020012297static struct hda_verb alc268_eapd_verbs[] = {
12298 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
12299 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
12300 { }
12301};
12302
Takashi Iwaid2738092007-08-16 14:59:45 +020012303/* Toshiba specific */
Takashi Iwaid2738092007-08-16 14:59:45 +020012304static struct hda_verb alc268_toshiba_verbs[] = {
12305 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12306 { } /* end */
12307};
12308
12309/* Acer specific */
Takashi Iwai889c4392007-08-23 18:56:52 +020012310/* bind volumes of both NID 0x02 and 0x03 */
Takashi Iwai6bc96852007-08-17 09:02:12 +020012311static struct hda_bind_ctls alc268_acer_bind_master_vol = {
12312 .ops = &snd_hda_bind_vol,
12313 .values = {
12314 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
12315 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
12316 0
12317 },
12318};
12319
Takashi Iwai889c4392007-08-23 18:56:52 +020012320/* mute/unmute internal speaker according to the hp jack and mute state */
12321static void alc268_acer_automute(struct hda_codec *codec, int force)
12322{
12323 struct alc_spec *spec = codec->spec;
12324 unsigned int mute;
12325
12326 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080012327 spec->jack_present = snd_hda_jack_detect(codec, 0x14);
Takashi Iwai889c4392007-08-23 18:56:52 +020012328 spec->sense_updated = 1;
12329 }
12330 if (spec->jack_present)
12331 mute = HDA_AMP_MUTE; /* mute internal speaker */
12332 else /* unmute internal speaker if necessary */
12333 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
12334 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
12335 HDA_AMP_MUTE, mute);
12336}
12337
12338
12339/* bind hp and internal speaker mute (with plug check) */
12340static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
12341 struct snd_ctl_elem_value *ucontrol)
12342{
12343 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
12344 long *valp = ucontrol->value.integer.value;
12345 int change;
12346
Takashi Iwai8de56b72009-07-24 16:51:47 +020012347 change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
Takashi Iwai889c4392007-08-23 18:56:52 +020012348 if (change)
12349 alc268_acer_automute(codec, 0);
12350 return change;
12351}
Takashi Iwaid2738092007-08-16 14:59:45 +020012352
Kailang Yang8ef355d2008-08-26 13:10:22 +020012353static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
12354 /* output mixer control */
12355 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12356 {
12357 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12358 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012359 .subdevice = HDA_SUBDEV_AMP_FLAG,
Kailang Yang8ef355d2008-08-26 13:10:22 +020012360 .info = snd_hda_mixer_amp_switch_info,
12361 .get = snd_hda_mixer_amp_switch_get,
12362 .put = alc268_acer_master_sw_put,
12363 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12364 },
12365 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
12366 { }
12367};
12368
Takashi Iwaid2738092007-08-16 14:59:45 +020012369static struct snd_kcontrol_new alc268_acer_mixer[] = {
12370 /* output mixer control */
12371 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12372 {
12373 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12374 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012375 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwaid2738092007-08-16 14:59:45 +020012376 .info = snd_hda_mixer_amp_switch_info,
12377 .get = snd_hda_mixer_amp_switch_get,
12378 .put = alc268_acer_master_sw_put,
12379 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12380 },
Takashi Iwai33bf17a2007-08-21 11:51:42 +020012381 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12382 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
12383 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
Takashi Iwaid2738092007-08-16 14:59:45 +020012384 { }
12385};
12386
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012387static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
12388 /* output mixer control */
12389 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12390 {
12391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12392 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012393 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012394 .info = snd_hda_mixer_amp_switch_info,
12395 .get = snd_hda_mixer_amp_switch_get,
12396 .put = alc268_acer_master_sw_put,
12397 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12398 },
12399 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12400 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
12401 { }
12402};
12403
Kailang Yang8ef355d2008-08-26 13:10:22 +020012404static struct hda_verb alc268_acer_aspire_one_verbs[] = {
12405 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
12406 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12407 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12408 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
12409 {0x23, AC_VERB_SET_CONNECT_SEL, 0x06},
12410 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, 0xa017},
12411 { }
12412};
12413
Takashi Iwaid2738092007-08-16 14:59:45 +020012414static struct hda_verb alc268_acer_verbs[] = {
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012415 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
12416 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaid2738092007-08-16 14:59:45 +020012417 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12418 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012419 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
12420 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaid2738092007-08-16 14:59:45 +020012421 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12422 { }
12423};
12424
12425/* unsolicited event for HP jack sensing */
Takashi Iwai42171c12009-05-08 14:11:43 +020012426#define alc268_toshiba_unsol_event alc262_hippo_unsol_event
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012427#define alc268_toshiba_setup alc262_hippo_setup
12428#define alc268_toshiba_automute alc262_hippo_automute
Takashi Iwaid2738092007-08-16 14:59:45 +020012429
12430static void alc268_acer_unsol_event(struct hda_codec *codec,
12431 unsigned int res)
12432{
Takashi Iwai889c4392007-08-23 18:56:52 +020012433 if ((res >> 26) != ALC880_HP_EVENT)
Takashi Iwaid2738092007-08-16 14:59:45 +020012434 return;
12435 alc268_acer_automute(codec, 1);
12436}
12437
Takashi Iwai889c4392007-08-23 18:56:52 +020012438static void alc268_acer_init_hook(struct hda_codec *codec)
12439{
12440 alc268_acer_automute(codec, 1);
12441}
12442
Kailang Yang8ef355d2008-08-26 13:10:22 +020012443/* toggle speaker-output according to the hp-jack state */
12444static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
12445{
12446 unsigned int present;
12447 unsigned char bits;
12448
Wu Fengguang864f92b2009-11-18 12:38:02 +080012449 present = snd_hda_jack_detect(codec, 0x15);
Kailang Yang8ef355d2008-08-26 13:10:22 +020012450 bits = present ? AMP_IN_MUTE(0) : 0;
12451 snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
12452 AMP_IN_MUTE(0), bits);
12453 snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1,
12454 AMP_IN_MUTE(0), bits);
12455}
12456
Kailang Yang8ef355d2008-08-26 13:10:22 +020012457static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
12458 unsigned int res)
12459{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012460 switch (res >> 26) {
12461 case ALC880_HP_EVENT:
Kailang Yang8ef355d2008-08-26 13:10:22 +020012462 alc268_aspire_one_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012463 break;
12464 case ALC880_MIC_EVENT:
12465 alc_mic_automute(codec);
12466 break;
12467 }
12468}
12469
12470static void alc268_acer_lc_setup(struct hda_codec *codec)
12471{
12472 struct alc_spec *spec = codec->spec;
12473 spec->ext_mic.pin = 0x18;
12474 spec->ext_mic.mux_idx = 0;
12475 spec->int_mic.pin = 0x12;
12476 spec->int_mic.mux_idx = 6;
12477 spec->auto_mic = 1;
Kailang Yang8ef355d2008-08-26 13:10:22 +020012478}
12479
12480static void alc268_acer_lc_init_hook(struct hda_codec *codec)
12481{
12482 alc268_aspire_one_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012483 alc_mic_automute(codec);
Kailang Yang8ef355d2008-08-26 13:10:22 +020012484}
12485
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012486static struct snd_kcontrol_new alc268_dell_mixer[] = {
12487 /* output mixer control */
12488 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
12489 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12490 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
12491 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
12492 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12493 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
12494 { }
12495};
12496
12497static struct hda_verb alc268_dell_verbs[] = {
12498 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12499 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12500 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012501 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012502 { }
12503};
12504
12505/* mute/unmute internal speaker according to the hp jack and mute state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012506static void alc268_dell_setup(struct hda_codec *codec)
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012507{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012508 struct alc_spec *spec = codec->spec;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012509
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012510 spec->autocfg.hp_pins[0] = 0x15;
12511 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012512 spec->ext_mic.pin = 0x18;
12513 spec->ext_mic.mux_idx = 0;
12514 spec->int_mic.pin = 0x19;
12515 spec->int_mic.mux_idx = 1;
12516 spec->auto_mic = 1;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012517}
12518
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012519static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
12520 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12521 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12522 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12523 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
12524 HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12525 HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
12526 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
12527 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
12528 { }
12529};
12530
12531static struct hda_verb alc267_quanta_il1_verbs[] = {
12532 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12533 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
12534 { }
12535};
12536
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012537static void alc267_quanta_il1_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012538{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012539 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012540 spec->autocfg.hp_pins[0] = 0x15;
12541 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012542 spec->ext_mic.pin = 0x18;
12543 spec->ext_mic.mux_idx = 0;
12544 spec->int_mic.pin = 0x19;
12545 spec->int_mic.mux_idx = 1;
12546 spec->auto_mic = 1;
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012547}
12548
Kailang Yanga361d842007-06-05 12:30:55 +020012549/*
12550 * generic initialization of ADC, input mixers and output mixers
12551 */
12552static struct hda_verb alc268_base_init_verbs[] = {
12553 /* Unmute DAC0-1 and set vol = 0 */
12554 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020012555 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020012556
12557 /*
12558 * Set up output mixers (0x0c - 0x0e)
12559 */
12560 /* set vol=0 to output mixers */
12561 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yanga361d842007-06-05 12:30:55 +020012562 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
12563
12564 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12565 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12566
12567 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
12568 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
12569 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
12570 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12571 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12572 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12573 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12574 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12575
12576 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12577 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12578 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
12579 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020012580 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwaiaef9d312008-02-19 13:16:41 +010012581
12582 /* set PCBEEP vol = 0, mute connections */
12583 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12584 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12585 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yanga361d842007-06-05 12:30:55 +020012586
Jiang Zhea9b3aa82007-12-20 13:13:13 +010012587 /* Unmute Selector 23h,24h and set the default input to mic-in */
Kailang Yangea1fb292008-08-26 12:58:38 +020012588
Jiang Zhea9b3aa82007-12-20 13:13:13 +010012589 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
12590 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
12591 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
12592 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020012593
Kailang Yanga361d842007-06-05 12:30:55 +020012594 { }
12595};
12596
12597/*
12598 * generic initialization of ADC, input mixers and output mixers
12599 */
12600static struct hda_verb alc268_volume_init_verbs[] = {
12601 /* set output DAC */
Takashi Iwai4cfb91c2009-01-23 12:53:09 +010012602 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12603 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020012604
12605 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12606 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12607 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12608 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12609 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12610
Kailang Yanga361d842007-06-05 12:30:55 +020012611 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yanga361d842007-06-05 12:30:55 +020012612 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12613 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12614
12615 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020012616 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020012617
Takashi Iwaiaef9d312008-02-19 13:16:41 +010012618 /* set PCBEEP vol = 0, mute connections */
12619 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12620 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12621 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yanga361d842007-06-05 12:30:55 +020012622
12623 { }
12624};
12625
Takashi Iwaifdbc6622009-08-19 00:18:10 +020012626static struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
12627 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12628 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
12629 { } /* end */
12630};
12631
Kailang Yanga361d842007-06-05 12:30:55 +020012632static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
12633 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12634 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
Takashi Iwaifdbc6622009-08-19 00:18:10 +020012635 _DEFINE_CAPSRC(1),
Kailang Yanga361d842007-06-05 12:30:55 +020012636 { } /* end */
12637};
12638
12639static struct snd_kcontrol_new alc268_capture_mixer[] = {
12640 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12641 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
12642 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
12643 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
Takashi Iwaifdbc6622009-08-19 00:18:10 +020012644 _DEFINE_CAPSRC(2),
Kailang Yanga361d842007-06-05 12:30:55 +020012645 { } /* end */
12646};
12647
12648static struct hda_input_mux alc268_capture_source = {
12649 .num_items = 4,
12650 .items = {
12651 { "Mic", 0x0 },
12652 { "Front Mic", 0x1 },
12653 { "Line", 0x2 },
12654 { "CD", 0x3 },
12655 },
12656};
12657
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012658static struct hda_input_mux alc268_acer_capture_source = {
12659 .num_items = 3,
12660 .items = {
12661 { "Mic", 0x0 },
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012662 { "Internal Mic", 0x1 },
12663 { "Line", 0x2 },
12664 },
12665};
12666
12667static struct hda_input_mux alc268_acer_dmic_capture_source = {
12668 .num_items = 3,
12669 .items = {
12670 { "Mic", 0x0 },
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012671 { "Internal Mic", 0x6 },
12672 { "Line", 0x2 },
12673 },
12674};
12675
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010012676#ifdef CONFIG_SND_DEBUG
12677static struct snd_kcontrol_new alc268_test_mixer[] = {
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010012678 /* Volume widgets */
12679 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
12680 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
12681 HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
12682 HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
12683 HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
12684 HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
12685 HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
12686 HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
12687 HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
12688 HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
12689 HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
12690 HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
12691 HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
Takashi Iwaif0747ee2008-01-15 11:41:41 +010012692 /* The below appears problematic on some hardwares */
12693 /*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010012694 HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12695 HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
12696 HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
12697 HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
12698
12699 /* Modes for retasking pin widgets */
12700 ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
12701 ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
12702 ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
12703 ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
12704
12705 /* Controls for GPIO pins, assuming they are configured as outputs */
12706 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
12707 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
12708 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
12709 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
12710
12711 /* Switches to allow the digital SPDIF output pin to be enabled.
12712 * The ALC268 does not have an SPDIF input.
12713 */
12714 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
12715
12716 /* A switch allowing EAPD to be enabled. Some laptops seem to use
12717 * this output to turn on an external amplifier.
12718 */
12719 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
12720 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
12721
12722 { } /* end */
12723};
12724#endif
12725
Kailang Yanga361d842007-06-05 12:30:55 +020012726/* create input playback/capture controls for the given pin */
12727static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
12728 const char *ctlname, int idx)
12729{
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012730 hda_nid_t dac;
Kailang Yanga361d842007-06-05 12:30:55 +020012731 int err;
12732
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012733 switch (nid) {
12734 case 0x14:
12735 case 0x16:
12736 dac = 0x02;
12737 break;
12738 case 0x15:
12739 dac = 0x03;
12740 break;
12741 default:
12742 return 0;
12743 }
12744 if (spec->multiout.dac_nids[0] != dac &&
12745 spec->multiout.dac_nids[1] != dac) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012746 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012747 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
Kailang Yanga361d842007-06-05 12:30:55 +020012748 HDA_OUTPUT));
12749 if (err < 0)
12750 return err;
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012751 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
12752 }
12753
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012754 if (nid != 0x16)
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012755 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
Kailang Yanga361d842007-06-05 12:30:55 +020012756 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012757 else /* mono */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012758 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012759 HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
Kailang Yanga361d842007-06-05 12:30:55 +020012760 if (err < 0)
12761 return err;
12762 return 0;
12763}
12764
12765/* add playback controls from the parsed DAC table */
12766static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
12767 const struct auto_pin_cfg *cfg)
12768{
12769 hda_nid_t nid;
12770 int err;
12771
Kailang Yanga361d842007-06-05 12:30:55 +020012772 spec->multiout.dac_nids = spec->private_dac_nids;
Kailang Yanga361d842007-06-05 12:30:55 +020012773
12774 nid = cfg->line_out_pins[0];
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012775 if (nid) {
12776 const char *name;
12777 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
12778 name = "Speaker";
12779 else
12780 name = "Front";
12781 err = alc268_new_analog_output(spec, nid, name, 0);
12782 if (err < 0)
12783 return err;
12784 }
Kailang Yanga361d842007-06-05 12:30:55 +020012785
12786 nid = cfg->speaker_pins[0];
12787 if (nid == 0x1d) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012788 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
Kailang Yanga361d842007-06-05 12:30:55 +020012789 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
12790 if (err < 0)
12791 return err;
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012792 } else {
12793 err = alc268_new_analog_output(spec, nid, "Speaker", 0);
12794 if (err < 0)
12795 return err;
Kailang Yanga361d842007-06-05 12:30:55 +020012796 }
12797 nid = cfg->hp_pins[0];
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012798 if (nid) {
12799 err = alc268_new_analog_output(spec, nid, "Headphone", 0);
12800 if (err < 0)
12801 return err;
12802 }
Kailang Yanga361d842007-06-05 12:30:55 +020012803
12804 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
12805 if (nid == 0x16) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020012806 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020012807 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
Kailang Yanga361d842007-06-05 12:30:55 +020012808 if (err < 0)
12809 return err;
12810 }
Kailang Yangea1fb292008-08-26 12:58:38 +020012811 return 0;
Kailang Yanga361d842007-06-05 12:30:55 +020012812}
12813
12814/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020012815static int alc268_auto_create_input_ctls(struct hda_codec *codec,
Kailang Yanga361d842007-06-05 12:30:55 +020012816 const struct auto_pin_cfg *cfg)
12817{
Takashi Iwai05f5f472009-08-25 13:10:18 +020012818 return alc_auto_create_input_ctls(codec, cfg, 0, 0x23, 0x24);
Kailang Yanga361d842007-06-05 12:30:55 +020012819}
12820
Takashi Iwaie9af4f32009-08-29 23:23:08 +020012821static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
12822 hda_nid_t nid, int pin_type)
12823{
12824 int idx;
12825
12826 alc_set_pin_output(codec, nid, pin_type);
12827 if (nid == 0x14 || nid == 0x16)
12828 idx = 0;
12829 else
12830 idx = 1;
12831 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
12832}
12833
12834static void alc268_auto_init_multi_out(struct hda_codec *codec)
12835{
12836 struct alc_spec *spec = codec->spec;
12837 hda_nid_t nid = spec->autocfg.line_out_pins[0];
12838 if (nid) {
12839 int pin_type = get_pin_type(spec->autocfg.line_out_type);
12840 alc268_auto_set_output_and_unmute(codec, nid, pin_type);
12841 }
12842}
12843
12844static void alc268_auto_init_hp_out(struct hda_codec *codec)
12845{
12846 struct alc_spec *spec = codec->spec;
12847 hda_nid_t pin;
12848
12849 pin = spec->autocfg.hp_pins[0];
12850 if (pin)
12851 alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
12852 pin = spec->autocfg.speaker_pins[0];
12853 if (pin)
12854 alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
12855}
12856
Kailang Yanga361d842007-06-05 12:30:55 +020012857static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
12858{
12859 struct alc_spec *spec = codec->spec;
12860 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
12861 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
12862 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
12863 unsigned int dac_vol1, dac_vol2;
12864
Takashi Iwaie9af4f32009-08-29 23:23:08 +020012865 if (line_nid == 0x1d || speaker_nid == 0x1d) {
Kailang Yanga361d842007-06-05 12:30:55 +020012866 snd_hda_codec_write(codec, speaker_nid, 0,
12867 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
Takashi Iwaie9af4f32009-08-29 23:23:08 +020012868 /* mute mixer inputs from 0x1d */
Kailang Yanga361d842007-06-05 12:30:55 +020012869 snd_hda_codec_write(codec, 0x0f, 0,
12870 AC_VERB_SET_AMP_GAIN_MUTE,
12871 AMP_IN_UNMUTE(1));
12872 snd_hda_codec_write(codec, 0x10, 0,
12873 AC_VERB_SET_AMP_GAIN_MUTE,
12874 AMP_IN_UNMUTE(1));
12875 } else {
Takashi Iwaie9af4f32009-08-29 23:23:08 +020012876 /* unmute mixer inputs from 0x1d */
Kailang Yanga361d842007-06-05 12:30:55 +020012877 snd_hda_codec_write(codec, 0x0f, 0,
12878 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
12879 snd_hda_codec_write(codec, 0x10, 0,
12880 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
12881 }
12882
12883 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */
Kailang Yangea1fb292008-08-26 12:58:38 +020012884 if (line_nid == 0x14)
Kailang Yanga361d842007-06-05 12:30:55 +020012885 dac_vol2 = AMP_OUT_ZERO;
12886 else if (line_nid == 0x15)
12887 dac_vol1 = AMP_OUT_ZERO;
Kailang Yangea1fb292008-08-26 12:58:38 +020012888 if (hp_nid == 0x14)
Kailang Yanga361d842007-06-05 12:30:55 +020012889 dac_vol2 = AMP_OUT_ZERO;
12890 else if (hp_nid == 0x15)
12891 dac_vol1 = AMP_OUT_ZERO;
12892 if (line_nid != 0x16 || hp_nid != 0x16 ||
12893 spec->autocfg.line_out_pins[1] != 0x16 ||
12894 spec->autocfg.line_out_pins[2] != 0x16)
12895 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
12896
12897 snd_hda_codec_write(codec, 0x02, 0,
12898 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
12899 snd_hda_codec_write(codec, 0x03, 0,
12900 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
12901}
12902
Sasha Alexandrdef319f2009-06-16 16:00:15 -040012903/* pcm configuration: identical with ALC880 */
Kailang Yanga361d842007-06-05 12:30:55 +020012904#define alc268_pcm_analog_playback alc880_pcm_analog_playback
12905#define alc268_pcm_analog_capture alc880_pcm_analog_capture
Takashi Iwai63300792008-01-24 15:31:36 +010012906#define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
Kailang Yanga361d842007-06-05 12:30:55 +020012907#define alc268_pcm_digital_playback alc880_pcm_digital_playback
12908
12909/*
12910 * BIOS auto configuration
12911 */
12912static int alc268_parse_auto_config(struct hda_codec *codec)
12913{
12914 struct alc_spec *spec = codec->spec;
12915 int err;
12916 static hda_nid_t alc268_ignore[] = { 0 };
12917
12918 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
12919 alc268_ignore);
12920 if (err < 0)
12921 return err;
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010012922 if (!spec->autocfg.line_outs) {
12923 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
12924 spec->multiout.max_channels = 2;
12925 spec->no_analog = 1;
12926 goto dig_only;
12927 }
Kailang Yanga361d842007-06-05 12:30:55 +020012928 return 0; /* can't find valid BIOS pin config */
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010012929 }
Kailang Yanga361d842007-06-05 12:30:55 +020012930 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
12931 if (err < 0)
12932 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020012933 err = alc268_auto_create_input_ctls(codec, &spec->autocfg);
Kailang Yanga361d842007-06-05 12:30:55 +020012934 if (err < 0)
12935 return err;
12936
12937 spec->multiout.max_channels = 2;
12938
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010012939 dig_only:
Kailang Yanga361d842007-06-05 12:30:55 +020012940 /* digital only support output */
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010012941 if (spec->autocfg.dig_outs) {
Kailang Yanga361d842007-06-05 12:30:55 +020012942 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010012943 spec->dig_out_type = spec->autocfg.dig_out_type[0];
12944 }
Takashi Iwai603c4012008-07-30 15:01:44 +020012945 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010012946 add_mixer(spec, spec->kctls.list);
Kailang Yanga361d842007-06-05 12:30:55 +020012947
Takashi Iwai892981f2009-03-02 08:04:35 +010012948 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d)
Takashi Iwaid88897e2008-10-31 15:01:37 +010012949 add_mixer(spec, alc268_beep_mixer);
Takashi Iwaiaef9d312008-02-19 13:16:41 +010012950
Takashi Iwaid88897e2008-10-31 15:01:37 +010012951 add_verb(spec, alc268_volume_init_verbs);
Herton Ronaldo Krzesinski59085892009-08-11 22:33:09 -030012952 spec->num_mux_defs = 2;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020012953 spec->input_mux = &spec->private_imux[0];
Kailang Yanga361d842007-06-05 12:30:55 +020012954
Takashi Iwai776e1842007-08-29 15:07:11 +020012955 err = alc_auto_add_mic_boost(codec);
12956 if (err < 0)
12957 return err;
12958
Kailang Yang6227cdc2010-02-25 08:36:52 +010012959 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai1d955eb2009-06-29 11:33:53 +020012960
Kailang Yanga361d842007-06-05 12:30:55 +020012961 return 1;
12962}
12963
Kailang Yanga361d842007-06-05 12:30:55 +020012964#define alc268_auto_init_analog_input alc882_auto_init_analog_input
12965
12966/* init callback for auto-configuration model -- overriding the default init */
12967static void alc268_auto_init(struct hda_codec *codec)
12968{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010012969 struct alc_spec *spec = codec->spec;
Kailang Yanga361d842007-06-05 12:30:55 +020012970 alc268_auto_init_multi_out(codec);
12971 alc268_auto_init_hp_out(codec);
12972 alc268_auto_init_mono_speaker_out(codec);
12973 alc268_auto_init_analog_input(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010012974 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020012975 alc_inithook(codec);
Kailang Yanga361d842007-06-05 12:30:55 +020012976}
12977
12978/*
12979 * configuration and preset
12980 */
12981static const char *alc268_models[ALC268_MODEL_LAST] = {
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012982 [ALC267_QUANTA_IL1] = "quanta-il1",
Kailang Yanga361d842007-06-05 12:30:55 +020012983 [ALC268_3ST] = "3stack",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020012984 [ALC268_TOSHIBA] = "toshiba",
Takashi Iwaid2738092007-08-16 14:59:45 +020012985 [ALC268_ACER] = "acer",
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012986 [ALC268_ACER_DMIC] = "acer-dmic",
Kailang Yang8ef355d2008-08-26 13:10:22 +020012987 [ALC268_ACER_ASPIRE_ONE] = "acer-aspire",
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012988 [ALC268_DELL] = "dell",
Mirco Tischlerf12462c2008-02-04 12:33:59 +010012989 [ALC268_ZEPTO] = "zepto",
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010012990#ifdef CONFIG_SND_DEBUG
12991 [ALC268_TEST] = "test",
12992#endif
Kailang Yanga361d842007-06-05 12:30:55 +020012993 [ALC268_AUTO] = "auto",
12994};
12995
12996static struct snd_pci_quirk alc268_cfg_tbl[] = {
Takashi Iwaia0b8f7d2008-04-22 19:39:49 +020012997 SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012998 SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
Andy Shevchenkodafc8352008-01-25 11:53:50 +010012999 SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010013000 SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
Andy Shevchenko29a52c22008-01-24 17:29:00 +010013001 SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
Kailang Yang8ef355d2008-08-26 13:10:22 +020013002 SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
13003 ALC268_ACER_ASPIRE_ONE),
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013004 SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
Daniel T Chena1bf8082009-11-01 18:32:29 -050013005 SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
13006 "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
Takashi Iwai33d78672009-09-08 11:03:41 +020013007 /* almost compatible with toshiba but with optional digital outs;
13008 * auto-probing seems working fine
13009 */
Takashi Iwai8871e5b2009-06-02 01:02:50 +020013010 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP TX25xx series",
Takashi Iwai33d78672009-09-08 11:03:41 +020013011 ALC268_AUTO),
Kailang Yanga361d842007-06-05 12:30:55 +020013012 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
Takashi Iwai8871e5b2009-06-02 01:02:50 +020013013 SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
Tony Vroon378bd6a2008-06-04 12:08:30 +020013014 SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
Takashi Iwaib875bf32007-09-06 15:00:27 +020013015 SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013016 SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
Takashi Iwai8871e5b2009-06-02 01:02:50 +020013017 SND_PCI_QUIRK(0x1854, 0x1775, "LG R510", ALC268_DELL),
Kailang Yanga361d842007-06-05 12:30:55 +020013018 {}
13019};
13020
Takashi Iwai3abf2f32009-08-19 20:05:02 +020013021/* Toshiba laptops have no unique PCI SSID but only codec SSID */
13022static struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
13023 SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
13024 SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
13025 SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
13026 ALC268_TOSHIBA),
13027 {}
13028};
13029
Kailang Yanga361d842007-06-05 12:30:55 +020013030static struct alc_config_preset alc268_presets[] = {
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013031 [ALC267_QUANTA_IL1] = {
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013032 .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
13033 alc268_capture_nosrc_mixer },
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013034 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13035 alc267_quanta_il1_verbs },
13036 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13037 .dac_nids = alc268_dac_nids,
13038 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13039 .adc_nids = alc268_adc_nids_alt,
13040 .hp_nid = 0x03,
13041 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13042 .channel_mode = alc268_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013043 .unsol_event = alc_sku_unsol_event,
13044 .setup = alc267_quanta_il1_setup,
13045 .init_hook = alc_inithook,
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013046 },
Kailang Yanga361d842007-06-05 12:30:55 +020013047 [ALC268_3ST] = {
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013048 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
13049 alc268_beep_mixer },
Kailang Yanga361d842007-06-05 12:30:55 +020013050 .init_verbs = { alc268_base_init_verbs },
13051 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13052 .dac_nids = alc268_dac_nids,
13053 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13054 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013055 .capsrc_nids = alc268_capsrc_nids,
Kailang Yanga361d842007-06-05 12:30:55 +020013056 .hp_nid = 0x03,
13057 .dig_out_nid = ALC268_DIGOUT_NID,
13058 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13059 .channel_mode = alc268_modes,
13060 .input_mux = &alc268_capture_source,
13061 },
Kailang Yangd1a991a2007-08-15 16:21:59 +020013062 [ALC268_TOSHIBA] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020013063 .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013064 alc268_beep_mixer },
Takashi Iwaid2738092007-08-16 14:59:45 +020013065 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13066 alc268_toshiba_verbs },
Kailang Yangd1a991a2007-08-15 16:21:59 +020013067 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13068 .dac_nids = alc268_dac_nids,
13069 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13070 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013071 .capsrc_nids = alc268_capsrc_nids,
Kailang Yangd1a991a2007-08-15 16:21:59 +020013072 .hp_nid = 0x03,
13073 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13074 .channel_mode = alc268_modes,
13075 .input_mux = &alc268_capture_source,
Takashi Iwaid2738092007-08-16 14:59:45 +020013076 .unsol_event = alc268_toshiba_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013077 .setup = alc268_toshiba_setup,
13078 .init_hook = alc268_toshiba_automute,
Takashi Iwaid2738092007-08-16 14:59:45 +020013079 },
13080 [ALC268_ACER] = {
Takashi Iwai432fd132009-09-30 08:13:44 +020013081 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013082 alc268_beep_mixer },
Takashi Iwaid2738092007-08-16 14:59:45 +020013083 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13084 alc268_acer_verbs },
13085 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13086 .dac_nids = alc268_dac_nids,
13087 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13088 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013089 .capsrc_nids = alc268_capsrc_nids,
Takashi Iwaid2738092007-08-16 14:59:45 +020013090 .hp_nid = 0x02,
13091 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13092 .channel_mode = alc268_modes,
Takashi Iwai0ccb5412008-03-06 16:58:35 +010013093 .input_mux = &alc268_acer_capture_source,
Takashi Iwaid2738092007-08-16 14:59:45 +020013094 .unsol_event = alc268_acer_unsol_event,
Takashi Iwai889c4392007-08-23 18:56:52 +020013095 .init_hook = alc268_acer_init_hook,
Kailang Yangd1a991a2007-08-15 16:21:59 +020013096 },
Takashi Iwaic238b4f2008-11-05 14:57:20 +010013097 [ALC268_ACER_DMIC] = {
13098 .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
13099 alc268_beep_mixer },
13100 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13101 alc268_acer_verbs },
13102 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13103 .dac_nids = alc268_dac_nids,
13104 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13105 .adc_nids = alc268_adc_nids_alt,
13106 .capsrc_nids = alc268_capsrc_nids,
13107 .hp_nid = 0x02,
13108 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13109 .channel_mode = alc268_modes,
13110 .input_mux = &alc268_acer_dmic_capture_source,
13111 .unsol_event = alc268_acer_unsol_event,
13112 .init_hook = alc268_acer_init_hook,
13113 },
Kailang Yang8ef355d2008-08-26 13:10:22 +020013114 [ALC268_ACER_ASPIRE_ONE] = {
13115 .mixers = { alc268_acer_aspire_one_mixer,
Takashi Iwai22971e32009-02-10 11:56:44 +010013116 alc268_beep_mixer,
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013117 alc268_capture_nosrc_mixer },
Kailang Yang8ef355d2008-08-26 13:10:22 +020013118 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13119 alc268_acer_aspire_one_verbs },
13120 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13121 .dac_nids = alc268_dac_nids,
13122 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13123 .adc_nids = alc268_adc_nids_alt,
13124 .capsrc_nids = alc268_capsrc_nids,
13125 .hp_nid = 0x03,
13126 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13127 .channel_mode = alc268_modes,
Kailang Yang8ef355d2008-08-26 13:10:22 +020013128 .unsol_event = alc268_acer_lc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013129 .setup = alc268_acer_lc_setup,
Kailang Yang8ef355d2008-08-26 13:10:22 +020013130 .init_hook = alc268_acer_lc_init_hook,
13131 },
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013132 [ALC268_DELL] = {
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013133 .mixers = { alc268_dell_mixer, alc268_beep_mixer,
13134 alc268_capture_nosrc_mixer },
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013135 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13136 alc268_dell_verbs },
13137 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13138 .dac_nids = alc268_dac_nids,
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013139 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13140 .adc_nids = alc268_adc_nids_alt,
13141 .capsrc_nids = alc268_capsrc_nids,
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013142 .hp_nid = 0x02,
13143 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13144 .channel_mode = alc268_modes,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020013145 .unsol_event = alc_sku_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013146 .setup = alc268_dell_setup,
13147 .init_hook = alc_inithook,
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013148 },
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013149 [ALC268_ZEPTO] = {
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013150 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
13151 alc268_beep_mixer },
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013152 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13153 alc268_toshiba_verbs },
13154 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13155 .dac_nids = alc268_dac_nids,
13156 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13157 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013158 .capsrc_nids = alc268_capsrc_nids,
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013159 .hp_nid = 0x03,
13160 .dig_out_nid = ALC268_DIGOUT_NID,
13161 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13162 .channel_mode = alc268_modes,
13163 .input_mux = &alc268_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013164 .setup = alc268_toshiba_setup,
13165 .init_hook = alc268_toshiba_automute,
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013166 },
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013167#ifdef CONFIG_SND_DEBUG
13168 [ALC268_TEST] = {
13169 .mixers = { alc268_test_mixer, alc268_capture_mixer },
13170 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13171 alc268_volume_init_verbs },
13172 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13173 .dac_nids = alc268_dac_nids,
13174 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13175 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013176 .capsrc_nids = alc268_capsrc_nids,
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013177 .hp_nid = 0x03,
13178 .dig_out_nid = ALC268_DIGOUT_NID,
13179 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13180 .channel_mode = alc268_modes,
13181 .input_mux = &alc268_capture_source,
13182 },
13183#endif
Kailang Yanga361d842007-06-05 12:30:55 +020013184};
13185
13186static int patch_alc268(struct hda_codec *codec)
13187{
13188 struct alc_spec *spec;
13189 int board_config;
Takashi Iwai22971e32009-02-10 11:56:44 +010013190 int i, has_beep, err;
Kailang Yanga361d842007-06-05 12:30:55 +020013191
Julia Lawallef86f582009-12-19 08:18:03 +010013192 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yanga361d842007-06-05 12:30:55 +020013193 if (spec == NULL)
13194 return -ENOMEM;
13195
13196 codec->spec = spec;
13197
13198 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
13199 alc268_models,
13200 alc268_cfg_tbl);
13201
Takashi Iwai3abf2f32009-08-19 20:05:02 +020013202 if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
13203 board_config = snd_hda_check_board_codec_sid_config(codec,
13204 ALC882_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
13205
Kailang Yanga361d842007-06-05 12:30:55 +020013206 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020013207 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
13208 codec->chip_name);
Kailang Yanga361d842007-06-05 12:30:55 +020013209 board_config = ALC268_AUTO;
13210 }
13211
13212 if (board_config == ALC268_AUTO) {
13213 /* automatic parse from the BIOS config */
13214 err = alc268_parse_auto_config(codec);
13215 if (err < 0) {
13216 alc_free(codec);
13217 return err;
13218 } else if (!err) {
13219 printk(KERN_INFO
13220 "hda_codec: Cannot set up configuration "
13221 "from BIOS. Using base mode...\n");
13222 board_config = ALC268_3ST;
13223 }
13224 }
13225
13226 if (board_config != ALC268_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020013227 setup_preset(codec, &alc268_presets[board_config]);
Kailang Yanga361d842007-06-05 12:30:55 +020013228
Kailang Yanga361d842007-06-05 12:30:55 +020013229 spec->stream_analog_playback = &alc268_pcm_analog_playback;
13230 spec->stream_analog_capture = &alc268_pcm_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +010013231 spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
Kailang Yanga361d842007-06-05 12:30:55 +020013232
Kailang Yanga361d842007-06-05 12:30:55 +020013233 spec->stream_digital_playback = &alc268_pcm_digital_playback;
13234
Takashi Iwai22971e32009-02-10 11:56:44 +010013235 has_beep = 0;
13236 for (i = 0; i < spec->num_mixers; i++) {
13237 if (spec->mixers[i] == alc268_beep_mixer) {
13238 has_beep = 1;
13239 break;
13240 }
13241 }
13242
13243 if (has_beep) {
13244 err = snd_hda_attach_beep_device(codec, 0x1);
13245 if (err < 0) {
13246 alc_free(codec);
13247 return err;
13248 }
13249 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
13250 /* override the amp caps for beep generator */
13251 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013252 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
13253 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
13254 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
13255 (0 << AC_AMPCAP_MUTE_SHIFT));
Takashi Iwai22971e32009-02-10 11:56:44 +010013256 }
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013257
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013258 if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013259 /* check whether NID 0x07 is valid */
13260 unsigned int wcap = get_wcaps(codec, 0x07);
Takashi Iwai85860c02008-02-19 15:00:15 +010013261 int i;
Kailang Yanga361d842007-06-05 12:30:55 +020013262
Takashi Iwaidefb5ab2009-10-07 15:12:27 +020013263 spec->capsrc_nids = alc268_capsrc_nids;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013264 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020013265 wcap = get_wcaps_type(wcap);
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013266 if (spec->auto_mic ||
13267 wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013268 spec->adc_nids = alc268_adc_nids_alt;
13269 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
Takashi Iwaidefb5ab2009-10-07 15:12:27 +020013270 if (spec->auto_mic)
13271 fixup_automic_adc(codec);
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013272 if (spec->auto_mic || spec->input_mux->num_items == 1)
13273 add_mixer(spec, alc268_capture_nosrc_mixer);
13274 else
13275 add_mixer(spec, alc268_capture_alt_mixer);
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013276 } else {
13277 spec->adc_nids = alc268_adc_nids;
13278 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
Takashi Iwaid88897e2008-10-31 15:01:37 +010013279 add_mixer(spec, alc268_capture_mixer);
Kailang Yanga361d842007-06-05 12:30:55 +020013280 }
Takashi Iwai85860c02008-02-19 15:00:15 +010013281 /* set default input source */
13282 for (i = 0; i < spec->num_adc_nids; i++)
13283 snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
13284 0, AC_VERB_SET_CONNECT_SEL,
Herton Ronaldo Krzesinski59085892009-08-11 22:33:09 -030013285 i < spec->num_mux_defs ?
13286 spec->input_mux[i].items[0].index :
Takashi Iwai85860c02008-02-19 15:00:15 +010013287 spec->input_mux->items[0].index);
Kailang Yanga361d842007-06-05 12:30:55 +020013288 }
Takashi Iwai2134ea42008-01-10 16:53:55 +010013289
13290 spec->vmaster_nid = 0x02;
13291
Kailang Yanga361d842007-06-05 12:30:55 +020013292 codec->patch_ops = alc_patch_ops;
13293 if (board_config == ALC268_AUTO)
13294 spec->init_hook = alc268_auto_init;
Kailang Yangea1fb292008-08-26 12:58:38 +020013295
Kailang Yanga361d842007-06-05 12:30:55 +020013296 return 0;
13297}
13298
13299/*
Kailang Yangf6a92242007-12-13 16:52:54 +010013300 * ALC269 channel source setting (2 channel)
13301 */
13302#define ALC269_DIGOUT_NID ALC880_DIGOUT_NID
13303
13304#define alc269_dac_nids alc260_dac_nids
13305
13306static hda_nid_t alc269_adc_nids[1] = {
13307 /* ADC1 */
Kailang Yangf53281e2008-07-18 12:36:43 +020013308 0x08,
13309};
13310
Takashi Iwaie01bf502008-08-21 16:25:07 +020013311static hda_nid_t alc269_capsrc_nids[1] = {
13312 0x23,
13313};
13314
Kailang Yang84898e82010-02-04 14:16:14 +010013315static hda_nid_t alc269vb_adc_nids[1] = {
13316 /* ADC1 */
13317 0x09,
13318};
13319
13320static hda_nid_t alc269vb_capsrc_nids[1] = {
13321 0x22,
13322};
13323
Takashi Iwaie01bf502008-08-21 16:25:07 +020013324/* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24),
13325 * not a mux!
13326 */
13327
Kailang Yangf6a92242007-12-13 16:52:54 +010013328#define alc269_modes alc260_modes
13329#define alc269_capture_source alc880_lg_lw_capture_source
13330
13331static struct snd_kcontrol_new alc269_base_mixer[] = {
13332 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13333 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13334 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
13335 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
13336 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13337 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13338 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13339 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13340 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13341 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
13342 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13343 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
13344 { } /* end */
13345};
13346
Kailang Yang60db6b52008-08-26 13:13:00 +020013347static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
13348 /* output mixer control */
13349 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13350 {
13351 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13352 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010013353 .subdevice = HDA_SUBDEV_AMP_FLAG,
Kailang Yang60db6b52008-08-26 13:13:00 +020013354 .info = snd_hda_mixer_amp_switch_info,
13355 .get = snd_hda_mixer_amp_switch_get,
13356 .put = alc268_acer_master_sw_put,
13357 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
13358 },
13359 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13360 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13361 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13362 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13363 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13364 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yang60db6b52008-08-26 13:13:00 +020013365 { }
13366};
13367
Tony Vroon64154832008-11-06 15:08:49 +000013368static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
13369 /* output mixer control */
13370 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13371 {
13372 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13373 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010013374 .subdevice = HDA_SUBDEV_AMP_FLAG,
Tony Vroon64154832008-11-06 15:08:49 +000013375 .info = snd_hda_mixer_amp_switch_info,
13376 .get = snd_hda_mixer_amp_switch_get,
13377 .put = alc268_acer_master_sw_put,
13378 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
13379 },
13380 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13381 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13382 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13383 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13384 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13385 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
13386 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
13387 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
13388 HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT),
Tony Vroon64154832008-11-06 15:08:49 +000013389 { }
13390};
13391
Kailang Yang84898e82010-02-04 14:16:14 +010013392static struct snd_kcontrol_new alc269_laptop_mixer[] = {
Takashi Iwaiaa202452009-07-03 15:00:54 +020013393 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Darren Salt508f7112009-07-08 15:29:49 +010013394 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Takashi Iwaiaa202452009-07-03 15:00:54 +020013395 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Darren Salt508f7112009-07-08 15:29:49 +010013396 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yangf53281e2008-07-18 12:36:43 +020013397 { } /* end */
13398};
13399
Kailang Yang84898e82010-02-04 14:16:14 +010013400static struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
13401 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13402 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13403 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
13404 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13405 { } /* end */
13406};
13407
Kailang Yangf6a92242007-12-13 16:52:54 +010013408/* capture mixer elements */
Kailang Yang84898e82010-02-04 14:16:14 +010013409static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
13410 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
13411 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
13412 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13413 HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT),
13414 { } /* end */
13415};
13416
13417static struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
Kailang Yangf53281e2008-07-18 12:36:43 +020013418 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
13419 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
Takashi Iwai26f5df22008-11-03 17:39:46 +010013420 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13421 { } /* end */
13422};
13423
Kailang Yang84898e82010-02-04 14:16:14 +010013424static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
13425 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
13426 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
13427 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13428 HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT),
13429 { } /* end */
13430};
13431
13432static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
13433 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
13434 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
13435 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13436 { } /* end */
13437};
13438
Takashi Iwai26f5df22008-11-03 17:39:46 +010013439/* FSC amilo */
Kailang Yang84898e82010-02-04 14:16:14 +010013440#define alc269_fujitsu_mixer alc269_laptop_mixer
Kailang Yangf53281e2008-07-18 12:36:43 +020013441
Kailang Yang60db6b52008-08-26 13:13:00 +020013442static struct hda_verb alc269_quanta_fl1_verbs[] = {
13443 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13444 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13445 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13446 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13447 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13448 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13449 { }
13450};
13451
Tony Vroon64154832008-11-06 15:08:49 +000013452static struct hda_verb alc269_lifebook_verbs[] = {
13453 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13454 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
13455 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13456 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13457 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13458 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13459 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13460 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13461 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13462 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13463 { }
13464};
13465
Kailang Yang60db6b52008-08-26 13:13:00 +020013466/* toggle speaker-output according to the hp-jack state */
13467static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
13468{
13469 unsigned int present;
13470 unsigned char bits;
13471
Wu Fengguang864f92b2009-11-18 12:38:02 +080013472 present = snd_hda_jack_detect(codec, 0x15);
Kailang Yang60db6b52008-08-26 13:13:00 +020013473 bits = present ? AMP_IN_MUTE(0) : 0;
13474 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
13475 AMP_IN_MUTE(0), bits);
13476 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
13477 AMP_IN_MUTE(0), bits);
13478
13479 snd_hda_codec_write(codec, 0x20, 0,
13480 AC_VERB_SET_COEF_INDEX, 0x0c);
13481 snd_hda_codec_write(codec, 0x20, 0,
13482 AC_VERB_SET_PROC_COEF, 0x680);
13483
13484 snd_hda_codec_write(codec, 0x20, 0,
13485 AC_VERB_SET_COEF_INDEX, 0x0c);
13486 snd_hda_codec_write(codec, 0x20, 0,
13487 AC_VERB_SET_PROC_COEF, 0x480);
13488}
13489
Tony Vroon64154832008-11-06 15:08:49 +000013490/* toggle speaker-output according to the hp-jacks state */
13491static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
13492{
13493 unsigned int present;
13494 unsigned char bits;
13495
13496 /* Check laptop headphone socket */
Wu Fengguang864f92b2009-11-18 12:38:02 +080013497 present = snd_hda_jack_detect(codec, 0x15);
Tony Vroon64154832008-11-06 15:08:49 +000013498
13499 /* Check port replicator headphone socket */
Wu Fengguang864f92b2009-11-18 12:38:02 +080013500 present |= snd_hda_jack_detect(codec, 0x1a);
Tony Vroon64154832008-11-06 15:08:49 +000013501
13502 bits = present ? AMP_IN_MUTE(0) : 0;
13503 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
13504 AMP_IN_MUTE(0), bits);
13505 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
13506 AMP_IN_MUTE(0), bits);
13507
13508 snd_hda_codec_write(codec, 0x20, 0,
13509 AC_VERB_SET_COEF_INDEX, 0x0c);
13510 snd_hda_codec_write(codec, 0x20, 0,
13511 AC_VERB_SET_PROC_COEF, 0x680);
13512
13513 snd_hda_codec_write(codec, 0x20, 0,
13514 AC_VERB_SET_COEF_INDEX, 0x0c);
13515 snd_hda_codec_write(codec, 0x20, 0,
13516 AC_VERB_SET_PROC_COEF, 0x480);
13517}
13518
Tony Vroon64154832008-11-06 15:08:49 +000013519static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
13520{
13521 unsigned int present_laptop;
13522 unsigned int present_dock;
13523
Wu Fengguang864f92b2009-11-18 12:38:02 +080013524 present_laptop = snd_hda_jack_detect(codec, 0x18);
13525 present_dock = snd_hda_jack_detect(codec, 0x1b);
Tony Vroon64154832008-11-06 15:08:49 +000013526
13527 /* Laptop mic port overrides dock mic port, design decision */
13528 if (present_dock)
13529 snd_hda_codec_write(codec, 0x23, 0,
13530 AC_VERB_SET_CONNECT_SEL, 0x3);
13531 if (present_laptop)
13532 snd_hda_codec_write(codec, 0x23, 0,
13533 AC_VERB_SET_CONNECT_SEL, 0x0);
13534 if (!present_dock && !present_laptop)
13535 snd_hda_codec_write(codec, 0x23, 0,
13536 AC_VERB_SET_CONNECT_SEL, 0x1);
13537}
13538
Kailang Yang60db6b52008-08-26 13:13:00 +020013539static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
13540 unsigned int res)
13541{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013542 switch (res >> 26) {
13543 case ALC880_HP_EVENT:
Kailang Yang60db6b52008-08-26 13:13:00 +020013544 alc269_quanta_fl1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013545 break;
13546 case ALC880_MIC_EVENT:
13547 alc_mic_automute(codec);
13548 break;
13549 }
Kailang Yang60db6b52008-08-26 13:13:00 +020013550}
13551
Tony Vroon64154832008-11-06 15:08:49 +000013552static void alc269_lifebook_unsol_event(struct hda_codec *codec,
13553 unsigned int res)
13554{
13555 if ((res >> 26) == ALC880_HP_EVENT)
13556 alc269_lifebook_speaker_automute(codec);
13557 if ((res >> 26) == ALC880_MIC_EVENT)
13558 alc269_lifebook_mic_autoswitch(codec);
13559}
13560
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013561static void alc269_quanta_fl1_setup(struct hda_codec *codec)
13562{
13563 struct alc_spec *spec = codec->spec;
13564 spec->ext_mic.pin = 0x18;
13565 spec->ext_mic.mux_idx = 0;
13566 spec->int_mic.pin = 0x19;
13567 spec->int_mic.mux_idx = 1;
13568 spec->auto_mic = 1;
13569}
13570
Kailang Yang60db6b52008-08-26 13:13:00 +020013571static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
13572{
13573 alc269_quanta_fl1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013574 alc_mic_automute(codec);
Kailang Yang60db6b52008-08-26 13:13:00 +020013575}
13576
Tony Vroon64154832008-11-06 15:08:49 +000013577static void alc269_lifebook_init_hook(struct hda_codec *codec)
13578{
13579 alc269_lifebook_speaker_automute(codec);
13580 alc269_lifebook_mic_autoswitch(codec);
13581}
13582
Kailang Yang84898e82010-02-04 14:16:14 +010013583static struct hda_verb alc269_laptop_dmic_init_verbs[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020013584 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13585 {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
13586 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
13587 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
13588 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13589 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13590 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13591 {}
13592};
13593
Kailang Yang84898e82010-02-04 14:16:14 +010013594static struct hda_verb alc269_laptop_amic_init_verbs[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020013595 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13596 {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
13597 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
13598 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
13599 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13600 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13601 {}
13602};
13603
Kailang Yang84898e82010-02-04 14:16:14 +010013604static struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
13605 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
13606 {0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
13607 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
13608 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
13609 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13610 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13611 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13612 {}
13613};
13614
13615static struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
13616 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
13617 {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
13618 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
13619 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
13620 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13621 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13622 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
13623 {}
13624};
13625
Kailang Yang60db6b52008-08-26 13:13:00 +020013626/* toggle speaker-output according to the hp-jack state */
13627static void alc269_speaker_automute(struct hda_codec *codec)
13628{
Kailang Yangebb83ee2009-12-17 12:23:00 +010013629 struct alc_spec *spec = codec->spec;
13630 unsigned int nid = spec->autocfg.hp_pins[0];
Kailang Yang60db6b52008-08-26 13:13:00 +020013631 unsigned int present;
13632 unsigned char bits;
13633
Kailang Yangebb83ee2009-12-17 12:23:00 +010013634 present = snd_hda_jack_detect(codec, nid);
Kailang Yang60db6b52008-08-26 13:13:00 +020013635 bits = present ? AMP_IN_MUTE(0) : 0;
13636 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
13637 AMP_IN_MUTE(0), bits);
13638 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
13639 AMP_IN_MUTE(0), bits);
13640}
13641
Kailang Yang60db6b52008-08-26 13:13:00 +020013642/* unsolicited event for HP jack sensing */
Kailang Yang84898e82010-02-04 14:16:14 +010013643static void alc269_laptop_unsol_event(struct hda_codec *codec,
Kailang Yang60db6b52008-08-26 13:13:00 +020013644 unsigned int res)
13645{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013646 switch (res >> 26) {
13647 case ALC880_HP_EVENT:
Kailang Yang60db6b52008-08-26 13:13:00 +020013648 alc269_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013649 break;
13650 case ALC880_MIC_EVENT:
13651 alc_mic_automute(codec);
13652 break;
13653 }
Kailang Yang60db6b52008-08-26 13:13:00 +020013654}
13655
Kailang Yang84898e82010-02-04 14:16:14 +010013656static void alc269_laptop_dmic_setup(struct hda_codec *codec)
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013657{
13658 struct alc_spec *spec = codec->spec;
13659 spec->ext_mic.pin = 0x18;
13660 spec->ext_mic.mux_idx = 0;
13661 spec->int_mic.pin = 0x12;
13662 spec->int_mic.mux_idx = 5;
13663 spec->auto_mic = 1;
13664}
13665
Kailang Yang84898e82010-02-04 14:16:14 +010013666static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
13667{
13668 struct alc_spec *spec = codec->spec;
13669 spec->ext_mic.pin = 0x18;
13670 spec->ext_mic.mux_idx = 0;
13671 spec->int_mic.pin = 0x12;
13672 spec->int_mic.mux_idx = 6;
13673 spec->auto_mic = 1;
13674}
13675
13676static void alc269_laptop_amic_setup(struct hda_codec *codec)
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013677{
13678 struct alc_spec *spec = codec->spec;
13679 spec->ext_mic.pin = 0x18;
13680 spec->ext_mic.mux_idx = 0;
13681 spec->int_mic.pin = 0x19;
13682 spec->int_mic.mux_idx = 1;
13683 spec->auto_mic = 1;
13684}
13685
Kailang Yang84898e82010-02-04 14:16:14 +010013686static void alc269_laptop_inithook(struct hda_codec *codec)
Kailang Yang60db6b52008-08-26 13:13:00 +020013687{
13688 alc269_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013689 alc_mic_automute(codec);
Kailang Yang60db6b52008-08-26 13:13:00 +020013690}
13691
Kailang Yangf6a92242007-12-13 16:52:54 +010013692/*
13693 * generic initialization of ADC, input mixers and output mixers
13694 */
13695static struct hda_verb alc269_init_verbs[] = {
13696 /*
13697 * Unmute ADC0 and set the default input to mic-in
13698 */
Kailang Yang84898e82010-02-04 14:16:14 +010013699 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangf6a92242007-12-13 16:52:54 +010013700
13701 /*
Kailang Yang84898e82010-02-04 14:16:14 +010013702 * Set up output mixers (0x02 - 0x03)
Kailang Yangf6a92242007-12-13 16:52:54 +010013703 */
13704 /* set vol=0 to output mixers */
13705 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13706 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13707
13708 /* set up input amps for analog loopback */
13709 /* Amp Indices: DAC = 0, mixer = 1 */
13710 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13711 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13712 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13713 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13714 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13715 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13716
13717 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13718 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13719 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13720 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13721 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13722 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13723 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13724
13725 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13726 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangf6a92242007-12-13 16:52:54 +010013727
Kailang Yang84898e82010-02-04 14:16:14 +010013728 /* FIXME: use Mux-type input source selection */
Kailang Yangf6a92242007-12-13 16:52:54 +010013729 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
13730 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
Kailang Yang84898e82010-02-04 14:16:14 +010013731 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangf6a92242007-12-13 16:52:54 +010013732
13733 /* set EAPD */
13734 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
Kailang Yang84898e82010-02-04 14:16:14 +010013735 { }
13736};
13737
13738static struct hda_verb alc269vb_init_verbs[] = {
13739 /*
13740 * Unmute ADC0 and set the default input to mic-in
13741 */
13742 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13743
13744 /*
13745 * Set up output mixers (0x02 - 0x03)
13746 */
13747 /* set vol=0 to output mixers */
13748 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13749 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13750
13751 /* set up input amps for analog loopback */
13752 /* Amp Indices: DAC = 0, mixer = 1 */
13753 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13754 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13755 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13756 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13757 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13758 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
13759
13760 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13761 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13762 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
13763 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13764 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
13765 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13766 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13767
13768 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13769 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13770
13771 /* FIXME: use Mux-type input source selection */
13772 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
13773 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
13774 {0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
13775
13776 /* set EAPD */
13777 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
Kailang Yangf6a92242007-12-13 16:52:54 +010013778 { }
13779};
13780
Takashi Iwai9d0b71b2009-08-24 14:10:30 +020013781#define alc269_auto_create_multi_out_ctls \
13782 alc268_auto_create_multi_out_ctls
Takashi Iwai05f5f472009-08-25 13:10:18 +020013783#define alc269_auto_create_input_ctls \
13784 alc268_auto_create_input_ctls
Kailang Yangf6a92242007-12-13 16:52:54 +010013785
13786#ifdef CONFIG_SND_HDA_POWER_SAVE
13787#define alc269_loopbacks alc880_loopbacks
13788#endif
13789
Sasha Alexandrdef319f2009-06-16 16:00:15 -040013790/* pcm configuration: identical with ALC880 */
Kailang Yangf6a92242007-12-13 16:52:54 +010013791#define alc269_pcm_analog_playback alc880_pcm_analog_playback
13792#define alc269_pcm_analog_capture alc880_pcm_analog_capture
13793#define alc269_pcm_digital_playback alc880_pcm_digital_playback
13794#define alc269_pcm_digital_capture alc880_pcm_digital_capture
13795
Takashi Iwaif03d3112009-03-05 14:18:16 +010013796static struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
13797 .substreams = 1,
13798 .channels_min = 2,
13799 .channels_max = 8,
13800 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
13801 /* NID is set in alc_build_pcms */
13802 .ops = {
13803 .open = alc880_playback_pcm_open,
13804 .prepare = alc880_playback_pcm_prepare,
13805 .cleanup = alc880_playback_pcm_cleanup
13806 },
13807};
13808
13809static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
13810 .substreams = 1,
13811 .channels_min = 2,
13812 .channels_max = 2,
13813 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
13814 /* NID is set in alc_build_pcms */
13815};
13816
Kailang Yangf6a92242007-12-13 16:52:54 +010013817/*
13818 * BIOS auto configuration
13819 */
13820static int alc269_parse_auto_config(struct hda_codec *codec)
13821{
13822 struct alc_spec *spec = codec->spec;
Takashi Iwaicfb9fb52009-02-06 17:34:03 +010013823 int err;
Kailang Yangf6a92242007-12-13 16:52:54 +010013824 static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Kailang Yang84898e82010-02-04 14:16:14 +010013825 hda_nid_t real_capsrc_nids;
Kailang Yangf6a92242007-12-13 16:52:54 +010013826
13827 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
13828 alc269_ignore);
13829 if (err < 0)
13830 return err;
13831
13832 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
13833 if (err < 0)
13834 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020013835 err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
Kailang Yangf6a92242007-12-13 16:52:54 +010013836 if (err < 0)
13837 return err;
13838
13839 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
13840
Takashi Iwai0852d7a2009-02-11 11:35:15 +010013841 if (spec->autocfg.dig_outs)
Kailang Yangf6a92242007-12-13 16:52:54 +010013842 spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
13843
Takashi Iwai603c4012008-07-30 15:01:44 +020013844 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010013845 add_mixer(spec, spec->kctls.list);
Kailang Yangf6a92242007-12-13 16:52:54 +010013846
Kailang Yang84898e82010-02-04 14:16:14 +010013847 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) {
13848 add_verb(spec, alc269vb_init_verbs);
13849 real_capsrc_nids = alc269vb_capsrc_nids[0];
Kailang Yang6227cdc2010-02-25 08:36:52 +010013850 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
Kailang Yang84898e82010-02-04 14:16:14 +010013851 } else {
13852 add_verb(spec, alc269_init_verbs);
13853 real_capsrc_nids = alc269_capsrc_nids[0];
Kailang Yang6227cdc2010-02-25 08:36:52 +010013854 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Kailang Yang84898e82010-02-04 14:16:14 +010013855 }
13856
Kailang Yangf6a92242007-12-13 16:52:54 +010013857 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020013858 spec->input_mux = &spec->private_imux[0];
Takashi Iwaie01bf502008-08-21 16:25:07 +020013859 /* set default input source */
Kailang Yang84898e82010-02-04 14:16:14 +010013860 snd_hda_codec_write_cache(codec, real_capsrc_nids,
Takashi Iwaie01bf502008-08-21 16:25:07 +020013861 0, AC_VERB_SET_CONNECT_SEL,
13862 spec->input_mux->items[0].index);
Kailang Yangf6a92242007-12-13 16:52:54 +010013863
13864 err = alc_auto_add_mic_boost(codec);
13865 if (err < 0)
13866 return err;
13867
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013868 if (!spec->cap_mixer && !spec->no_analog)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020013869 set_capture_mixer(codec);
Kailang Yangf53281e2008-07-18 12:36:43 +020013870
Kailang Yangf6a92242007-12-13 16:52:54 +010013871 return 1;
13872}
13873
Takashi Iwaie9af4f32009-08-29 23:23:08 +020013874#define alc269_auto_init_multi_out alc268_auto_init_multi_out
13875#define alc269_auto_init_hp_out alc268_auto_init_hp_out
Kailang Yangf6a92242007-12-13 16:52:54 +010013876#define alc269_auto_init_analog_input alc882_auto_init_analog_input
13877
13878
13879/* init callback for auto-configuration model -- overriding the default init */
13880static void alc269_auto_init(struct hda_codec *codec)
13881{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010013882 struct alc_spec *spec = codec->spec;
Kailang Yangf6a92242007-12-13 16:52:54 +010013883 alc269_auto_init_multi_out(codec);
13884 alc269_auto_init_hp_out(codec);
13885 alc269_auto_init_analog_input(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010013886 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020013887 alc_inithook(codec);
Kailang Yangf6a92242007-12-13 16:52:54 +010013888}
13889
13890/*
13891 * configuration and preset
13892 */
13893static const char *alc269_models[ALC269_MODEL_LAST] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020013894 [ALC269_BASIC] = "basic",
Takashi Iwai2922c9a2008-08-27 18:12:42 +020013895 [ALC269_QUANTA_FL1] = "quanta",
Kailang Yang84898e82010-02-04 14:16:14 +010013896 [ALC269_AMIC] = "laptop-amic",
13897 [ALC269_DMIC] = "laptop-dmic",
Tony Vroon64154832008-11-06 15:08:49 +000013898 [ALC269_FUJITSU] = "fujitsu",
Takashi Iwai3d3792c2009-09-11 07:50:47 +020013899 [ALC269_LIFEBOOK] = "lifebook",
13900 [ALC269_AUTO] = "auto",
Kailang Yangf6a92242007-12-13 16:52:54 +010013901};
13902
13903static struct snd_pci_quirk alc269_cfg_tbl[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020013904 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
Kailang Yangf53281e2008-07-18 12:36:43 +020013905 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
Kailang Yang84898e82010-02-04 14:16:14 +010013906 ALC269_AMIC),
13907 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
13908 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
13909 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
13910 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
13911 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
13912 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
13913 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
13914 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
13915 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
13916 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_AMIC),
13917 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
13918 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
13919 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
13920 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
13921 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
13922 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
13923 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
13924 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
13925 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
13926 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
13927 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
13928 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
13929 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
13930 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
13931 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
13932 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
13933 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
13934 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
13935 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
13936 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
13937 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
13938 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
13939 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
13940 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
13941 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
13942 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
Kailang Yangf53281e2008-07-18 12:36:43 +020013943 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
Kailang Yang84898e82010-02-04 14:16:14 +010013944 ALC269_DMIC),
Kailang Yang60db6b52008-08-26 13:13:00 +020013945 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
Kailang Yang84898e82010-02-04 14:16:14 +010013946 ALC269_DMIC),
13947 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
13948 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
Takashi Iwai26f5df22008-11-03 17:39:46 +010013949 SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
Tony Vroon64154832008-11-06 15:08:49 +000013950 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
Kailang Yangf6a92242007-12-13 16:52:54 +010013951 {}
13952};
13953
13954static struct alc_config_preset alc269_presets[] = {
13955 [ALC269_BASIC] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010013956 .mixers = { alc269_base_mixer },
Kailang Yangf6a92242007-12-13 16:52:54 +010013957 .init_verbs = { alc269_init_verbs },
13958 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
13959 .dac_nids = alc269_dac_nids,
13960 .hp_nid = 0x03,
13961 .num_channel_mode = ARRAY_SIZE(alc269_modes),
13962 .channel_mode = alc269_modes,
13963 .input_mux = &alc269_capture_source,
13964 },
Kailang Yang60db6b52008-08-26 13:13:00 +020013965 [ALC269_QUANTA_FL1] = {
13966 .mixers = { alc269_quanta_fl1_mixer },
13967 .init_verbs = { alc269_init_verbs, alc269_quanta_fl1_verbs },
13968 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
13969 .dac_nids = alc269_dac_nids,
13970 .hp_nid = 0x03,
13971 .num_channel_mode = ARRAY_SIZE(alc269_modes),
13972 .channel_mode = alc269_modes,
13973 .input_mux = &alc269_capture_source,
13974 .unsol_event = alc269_quanta_fl1_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013975 .setup = alc269_quanta_fl1_setup,
Kailang Yang60db6b52008-08-26 13:13:00 +020013976 .init_hook = alc269_quanta_fl1_init_hook,
13977 },
Kailang Yang84898e82010-02-04 14:16:14 +010013978 [ALC269_AMIC] = {
13979 .mixers = { alc269_laptop_mixer },
13980 .cap_mixer = alc269_laptop_analog_capture_mixer,
Kailang Yangf53281e2008-07-18 12:36:43 +020013981 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010013982 alc269_laptop_amic_init_verbs },
Kailang Yangf53281e2008-07-18 12:36:43 +020013983 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
13984 .dac_nids = alc269_dac_nids,
13985 .hp_nid = 0x03,
13986 .num_channel_mode = ARRAY_SIZE(alc269_modes),
13987 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010013988 .unsol_event = alc269_laptop_unsol_event,
13989 .setup = alc269_laptop_amic_setup,
13990 .init_hook = alc269_laptop_inithook,
Kailang Yangf53281e2008-07-18 12:36:43 +020013991 },
Kailang Yang84898e82010-02-04 14:16:14 +010013992 [ALC269_DMIC] = {
13993 .mixers = { alc269_laptop_mixer },
13994 .cap_mixer = alc269_laptop_digital_capture_mixer,
Kailang Yangf53281e2008-07-18 12:36:43 +020013995 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010013996 alc269_laptop_dmic_init_verbs },
Kailang Yangf53281e2008-07-18 12:36:43 +020013997 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
13998 .dac_nids = alc269_dac_nids,
13999 .hp_nid = 0x03,
14000 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14001 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010014002 .unsol_event = alc269_laptop_unsol_event,
14003 .setup = alc269_laptop_dmic_setup,
14004 .init_hook = alc269_laptop_inithook,
14005 },
14006 [ALC269VB_AMIC] = {
14007 .mixers = { alc269vb_laptop_mixer },
14008 .cap_mixer = alc269vb_laptop_analog_capture_mixer,
14009 .init_verbs = { alc269vb_init_verbs,
14010 alc269vb_laptop_amic_init_verbs },
14011 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14012 .dac_nids = alc269_dac_nids,
14013 .hp_nid = 0x03,
14014 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14015 .channel_mode = alc269_modes,
14016 .unsol_event = alc269_laptop_unsol_event,
14017 .setup = alc269_laptop_amic_setup,
14018 .init_hook = alc269_laptop_inithook,
14019 },
14020 [ALC269VB_DMIC] = {
14021 .mixers = { alc269vb_laptop_mixer },
14022 .cap_mixer = alc269vb_laptop_digital_capture_mixer,
14023 .init_verbs = { alc269vb_init_verbs,
14024 alc269vb_laptop_dmic_init_verbs },
14025 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14026 .dac_nids = alc269_dac_nids,
14027 .hp_nid = 0x03,
14028 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14029 .channel_mode = alc269_modes,
14030 .unsol_event = alc269_laptop_unsol_event,
14031 .setup = alc269vb_laptop_dmic_setup,
14032 .init_hook = alc269_laptop_inithook,
Kailang Yangf53281e2008-07-18 12:36:43 +020014033 },
Takashi Iwai26f5df22008-11-03 17:39:46 +010014034 [ALC269_FUJITSU] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010014035 .mixers = { alc269_fujitsu_mixer },
Kailang Yang84898e82010-02-04 14:16:14 +010014036 .cap_mixer = alc269_laptop_digital_capture_mixer,
Takashi Iwai26f5df22008-11-03 17:39:46 +010014037 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010014038 alc269_laptop_dmic_init_verbs },
Takashi Iwai26f5df22008-11-03 17:39:46 +010014039 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14040 .dac_nids = alc269_dac_nids,
14041 .hp_nid = 0x03,
14042 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14043 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010014044 .unsol_event = alc269_laptop_unsol_event,
14045 .setup = alc269_laptop_dmic_setup,
14046 .init_hook = alc269_laptop_inithook,
Takashi Iwai26f5df22008-11-03 17:39:46 +010014047 },
Tony Vroon64154832008-11-06 15:08:49 +000014048 [ALC269_LIFEBOOK] = {
14049 .mixers = { alc269_lifebook_mixer },
14050 .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
14051 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14052 .dac_nids = alc269_dac_nids,
14053 .hp_nid = 0x03,
14054 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14055 .channel_mode = alc269_modes,
14056 .input_mux = &alc269_capture_source,
14057 .unsol_event = alc269_lifebook_unsol_event,
14058 .init_hook = alc269_lifebook_init_hook,
14059 },
Kailang Yangf6a92242007-12-13 16:52:54 +010014060};
14061
14062static int patch_alc269(struct hda_codec *codec)
14063{
14064 struct alc_spec *spec;
14065 int board_config;
14066 int err;
Kailang Yang84898e82010-02-04 14:16:14 +010014067 int is_alc269vb = 0;
Kailang Yangf6a92242007-12-13 16:52:54 +010014068
14069 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
14070 if (spec == NULL)
14071 return -ENOMEM;
14072
14073 codec->spec = spec;
14074
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +020014075 alc_fix_pll_init(codec, 0x20, 0x04, 15);
14076
Kailang Yang274693f2009-12-03 10:07:50 +010014077 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
14078 kfree(codec->chip_name);
14079 codec->chip_name = kstrdup("ALC259", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010014080 if (!codec->chip_name) {
14081 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010014082 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010014083 }
Kailang Yang84898e82010-02-04 14:16:14 +010014084 is_alc269vb = 1;
Kailang Yang274693f2009-12-03 10:07:50 +010014085 }
14086
Kailang Yangf6a92242007-12-13 16:52:54 +010014087 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
14088 alc269_models,
14089 alc269_cfg_tbl);
14090
14091 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020014092 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
14093 codec->chip_name);
Kailang Yangf6a92242007-12-13 16:52:54 +010014094 board_config = ALC269_AUTO;
14095 }
14096
14097 if (board_config == ALC269_AUTO) {
14098 /* automatic parse from the BIOS config */
14099 err = alc269_parse_auto_config(codec);
14100 if (err < 0) {
14101 alc_free(codec);
14102 return err;
14103 } else if (!err) {
14104 printk(KERN_INFO
14105 "hda_codec: Cannot set up configuration "
14106 "from BIOS. Using base mode...\n");
14107 board_config = ALC269_BASIC;
14108 }
14109 }
14110
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090014111 err = snd_hda_attach_beep_device(codec, 0x1);
14112 if (err < 0) {
14113 alc_free(codec);
14114 return err;
14115 }
14116
Kailang Yangf6a92242007-12-13 16:52:54 +010014117 if (board_config != ALC269_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020014118 setup_preset(codec, &alc269_presets[board_config]);
Kailang Yangf6a92242007-12-13 16:52:54 +010014119
Kailang Yang84898e82010-02-04 14:16:14 +010014120 if (board_config == ALC269_QUANTA_FL1) {
Takashi Iwaif03d3112009-03-05 14:18:16 +010014121 /* Due to a hardware problem on Lenovo Ideadpad, we need to
14122 * fix the sample rate of analog I/O to 44.1kHz
14123 */
14124 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
14125 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
14126 } else {
14127 spec->stream_analog_playback = &alc269_pcm_analog_playback;
14128 spec->stream_analog_capture = &alc269_pcm_analog_capture;
14129 }
Kailang Yangf6a92242007-12-13 16:52:54 +010014130 spec->stream_digital_playback = &alc269_pcm_digital_playback;
14131 spec->stream_digital_capture = &alc269_pcm_digital_capture;
14132
Kailang Yang84898e82010-02-04 14:16:14 +010014133 if (!is_alc269vb) {
14134 spec->adc_nids = alc269_adc_nids;
14135 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
14136 spec->capsrc_nids = alc269_capsrc_nids;
14137 } else {
14138 spec->adc_nids = alc269vb_adc_nids;
14139 spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
14140 spec->capsrc_nids = alc269vb_capsrc_nids;
14141 }
14142
Takashi Iwaif9e336f2008-10-31 16:37:07 +010014143 if (!spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020014144 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010014145 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Kailang Yangf6a92242007-12-13 16:52:54 +010014146
Takashi Iwai100d5eb2009-08-10 11:55:51 +020014147 spec->vmaster_nid = 0x02;
14148
Kailang Yangf6a92242007-12-13 16:52:54 +010014149 codec->patch_ops = alc_patch_ops;
14150 if (board_config == ALC269_AUTO)
14151 spec->init_hook = alc269_auto_init;
14152#ifdef CONFIG_SND_HDA_POWER_SAVE
14153 if (!spec->loopback.amplist)
14154 spec->loopback.amplist = alc269_loopbacks;
14155#endif
14156
14157 return 0;
14158}
14159
14160/*
Kailang Yangdf694da2005-12-05 19:42:22 +010014161 * ALC861 channel source setting (2/6 channel selection for 3-stack)
14162 */
14163
14164/*
14165 * set the path ways for 2 channel output
14166 * need to set the codec line out and mic 1 pin widgets to inputs
14167 */
14168static struct hda_verb alc861_threestack_ch2_init[] = {
14169 /* set pin widget 1Ah (line in) for input */
14170 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014171 /* set pin widget 18h (mic1/2) for input, for mic also enable
14172 * the vref
14173 */
Kailang Yangdf694da2005-12-05 19:42:22 +010014174 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14175
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014176 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
14177#if 0
14178 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14179 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
14180#endif
Kailang Yangdf694da2005-12-05 19:42:22 +010014181 { } /* end */
14182};
14183/*
14184 * 6ch mode
14185 * need to set the codec line out and mic 1 pin widgets to outputs
14186 */
14187static struct hda_verb alc861_threestack_ch6_init[] = {
14188 /* set pin widget 1Ah (line in) for output (Back Surround)*/
14189 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14190 /* set pin widget 18h (mic1) for output (CLFE)*/
14191 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14192
14193 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014194 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010014195
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014196 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
14197#if 0
14198 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14199 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
14200#endif
Kailang Yangdf694da2005-12-05 19:42:22 +010014201 { } /* end */
14202};
14203
14204static struct hda_channel_mode alc861_threestack_modes[2] = {
14205 { 2, alc861_threestack_ch2_init },
14206 { 6, alc861_threestack_ch6_init },
14207};
Takashi Iwai22309c32006-08-09 16:57:28 +020014208/* Set mic1 as input and unmute the mixer */
14209static struct hda_verb alc861_uniwill_m31_ch2_init[] = {
14210 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14211 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14212 { } /* end */
14213};
14214/* Set mic1 as output and mute mixer */
14215static struct hda_verb alc861_uniwill_m31_ch4_init[] = {
14216 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14217 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14218 { } /* end */
14219};
14220
14221static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
14222 { 2, alc861_uniwill_m31_ch2_init },
14223 { 4, alc861_uniwill_m31_ch4_init },
14224};
Kailang Yangdf694da2005-12-05 19:42:22 +010014225
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014226/* Set mic1 and line-in as input and unmute the mixer */
14227static struct hda_verb alc861_asus_ch2_init[] = {
14228 /* set pin widget 1Ah (line in) for input */
14229 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014230 /* set pin widget 18h (mic1/2) for input, for mic also enable
14231 * the vref
14232 */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014233 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14234
14235 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
14236#if 0
14237 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14238 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
14239#endif
14240 { } /* end */
14241};
14242/* Set mic1 nad line-in as output and mute mixer */
14243static struct hda_verb alc861_asus_ch6_init[] = {
14244 /* set pin widget 1Ah (line in) for output (Back Surround)*/
14245 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14246 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
14247 /* set pin widget 18h (mic1) for output (CLFE)*/
14248 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14249 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
14250 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
14251 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
14252
14253 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
14254#if 0
14255 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14256 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
14257#endif
14258 { } /* end */
14259};
14260
14261static struct hda_channel_mode alc861_asus_modes[2] = {
14262 { 2, alc861_asus_ch2_init },
14263 { 6, alc861_asus_ch6_init },
14264};
14265
Kailang Yangdf694da2005-12-05 19:42:22 +010014266/* patch-ALC861 */
14267
14268static struct snd_kcontrol_new alc861_base_mixer[] = {
14269 /* output mixer control */
14270 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14271 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14272 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14273 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14274 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
14275
14276 /*Input mixer control */
14277 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14278 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14279 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14280 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14281 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14282 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14283 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14284 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14285 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14286 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014287
Kailang Yangdf694da2005-12-05 19:42:22 +010014288 { } /* end */
14289};
14290
14291static struct snd_kcontrol_new alc861_3ST_mixer[] = {
14292 /* output mixer control */
14293 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14294 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14295 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14296 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14297 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
14298
14299 /* Input mixer control */
14300 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14301 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14302 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14303 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14304 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14305 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14306 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14307 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14308 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14309 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014310
Kailang Yangdf694da2005-12-05 19:42:22 +010014311 {
14312 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14313 .name = "Channel Mode",
14314 .info = alc_ch_mode_info,
14315 .get = alc_ch_mode_get,
14316 .put = alc_ch_mode_put,
14317 .private_value = ARRAY_SIZE(alc861_threestack_modes),
14318 },
14319 { } /* end */
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014320};
14321
Takashi Iwaid1d985f2006-11-23 19:27:12 +010014322static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014323 /* output mixer control */
14324 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14325 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14326 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
Kailang Yangea1fb292008-08-26 12:58:38 +020014327
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014328 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014329};
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014330
Takashi Iwai22309c32006-08-09 16:57:28 +020014331static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
14332 /* output mixer control */
14333 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14334 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14335 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14336 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14337 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
14338
14339 /* Input mixer control */
14340 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14341 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14342 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14343 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14344 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14345 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14346 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14347 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14348 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14349 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014350
Takashi Iwai22309c32006-08-09 16:57:28 +020014351 {
14352 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14353 .name = "Channel Mode",
14354 .info = alc_ch_mode_info,
14355 .get = alc_ch_mode_get,
14356 .put = alc_ch_mode_put,
14357 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
14358 },
14359 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014360};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014361
14362static struct snd_kcontrol_new alc861_asus_mixer[] = {
14363 /* output mixer control */
14364 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14365 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14366 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14367 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14368 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
14369
14370 /* Input mixer control */
14371 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14372 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
14373 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14374 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14375 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14376 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14377 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14378 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14379 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014380 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
14381
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014382 {
14383 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14384 .name = "Channel Mode",
14385 .info = alc_ch_mode_info,
14386 .get = alc_ch_mode_get,
14387 .put = alc_ch_mode_put,
14388 .private_value = ARRAY_SIZE(alc861_asus_modes),
14389 },
14390 { }
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014391};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014392
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014393/* additional mixer */
Takashi Iwaid1d985f2006-11-23 19:27:12 +010014394static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014395 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14396 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014397 { }
14398};
14399
Kailang Yangdf694da2005-12-05 19:42:22 +010014400/*
14401 * generic initialization of ADC, input mixers and output mixers
14402 */
14403static struct hda_verb alc861_base_init_verbs[] = {
14404 /*
14405 * Unmute ADC0 and set the default input to mic-in
14406 */
14407 /* port-A for surround (rear panel) */
14408 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14409 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
14410 /* port-B for mic-in (rear panel) with vref */
14411 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14412 /* port-C for line-in (rear panel) */
14413 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14414 /* port-D for Front */
14415 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14416 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
14417 /* port-E for HP out (front panel) */
14418 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
14419 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010014420 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010014421 /* port-F for mic-in (front panel) with vref */
14422 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14423 /* port-G for CLFE (rear panel) */
14424 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14425 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
14426 /* port-H for side (rear panel) */
14427 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14428 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
14429 /* CD-in */
14430 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14431 /* route front mic to ADC1*/
14432 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
14433 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014434
Kailang Yangdf694da2005-12-05 19:42:22 +010014435 /* Unmute DAC0~3 & spdif out*/
14436 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14437 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14438 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14439 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14440 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020014441
Kailang Yangdf694da2005-12-05 19:42:22 +010014442 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14443 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14444 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14445 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14446 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014447
Kailang Yangdf694da2005-12-05 19:42:22 +010014448 /* Unmute Stereo Mixer 15 */
14449 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14450 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14451 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014452 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Kailang Yangdf694da2005-12-05 19:42:22 +010014453
14454 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14455 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14456 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14457 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14458 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14459 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14460 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14461 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014462 /* hp used DAC 3 (Front) */
14463 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014464 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14465
14466 { }
14467};
14468
14469static struct hda_verb alc861_threestack_init_verbs[] = {
14470 /*
14471 * Unmute ADC0 and set the default input to mic-in
14472 */
14473 /* port-A for surround (rear panel) */
14474 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14475 /* port-B for mic-in (rear panel) with vref */
14476 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14477 /* port-C for line-in (rear panel) */
14478 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14479 /* port-D for Front */
14480 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14481 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
14482 /* port-E for HP out (front panel) */
14483 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
14484 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010014485 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010014486 /* port-F for mic-in (front panel) with vref */
14487 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14488 /* port-G for CLFE (rear panel) */
14489 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14490 /* port-H for side (rear panel) */
14491 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14492 /* CD-in */
14493 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14494 /* route front mic to ADC1*/
14495 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
14496 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14497 /* Unmute DAC0~3 & spdif out*/
14498 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14499 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14500 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14501 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14502 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020014503
Kailang Yangdf694da2005-12-05 19:42:22 +010014504 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14505 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14506 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14507 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14508 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014509
Kailang Yangdf694da2005-12-05 19:42:22 +010014510 /* Unmute Stereo Mixer 15 */
14511 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14512 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14513 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014514 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Kailang Yangdf694da2005-12-05 19:42:22 +010014515
14516 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14517 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14518 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14519 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14520 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14521 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14522 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14523 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014524 /* hp used DAC 3 (Front) */
14525 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014526 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14527 { }
14528};
Takashi Iwai22309c32006-08-09 16:57:28 +020014529
14530static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
14531 /*
14532 * Unmute ADC0 and set the default input to mic-in
14533 */
14534 /* port-A for surround (rear panel) */
14535 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14536 /* port-B for mic-in (rear panel) with vref */
14537 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14538 /* port-C for line-in (rear panel) */
14539 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14540 /* port-D for Front */
14541 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14542 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
14543 /* port-E for HP out (front panel) */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014544 /* this has to be set to VREF80 */
14545 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
Takashi Iwai22309c32006-08-09 16:57:28 +020014546 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010014547 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Takashi Iwai22309c32006-08-09 16:57:28 +020014548 /* port-F for mic-in (front panel) with vref */
14549 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14550 /* port-G for CLFE (rear panel) */
14551 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14552 /* port-H for side (rear panel) */
14553 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
14554 /* CD-in */
14555 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14556 /* route front mic to ADC1*/
14557 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
14558 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14559 /* Unmute DAC0~3 & spdif out*/
14560 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14561 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14562 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14563 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14564 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020014565
Takashi Iwai22309c32006-08-09 16:57:28 +020014566 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14567 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14568 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14569 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14570 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014571
Takashi Iwai22309c32006-08-09 16:57:28 +020014572 /* Unmute Stereo Mixer 15 */
14573 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14574 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14575 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014576 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Takashi Iwai22309c32006-08-09 16:57:28 +020014577
14578 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14579 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14580 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14581 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14582 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14583 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14584 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14585 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014586 /* hp used DAC 3 (Front) */
14587 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Takashi Iwai22309c32006-08-09 16:57:28 +020014588 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14589 { }
14590};
14591
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014592static struct hda_verb alc861_asus_init_verbs[] = {
14593 /*
14594 * Unmute ADC0 and set the default input to mic-in
14595 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014596 /* port-A for surround (rear panel)
14597 * according to codec#0 this is the HP jack
14598 */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014599 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
14600 /* route front PCM to HP */
14601 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
14602 /* port-B for mic-in (rear panel) with vref */
14603 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14604 /* port-C for line-in (rear panel) */
14605 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14606 /* port-D for Front */
14607 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14608 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
14609 /* port-E for HP out (front panel) */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014610 /* this has to be set to VREF80 */
14611 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014612 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010014613 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014614 /* port-F for mic-in (front panel) with vref */
14615 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14616 /* port-G for CLFE (rear panel) */
14617 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14618 /* port-H for side (rear panel) */
14619 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14620 /* CD-in */
14621 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
14622 /* route front mic to ADC1*/
14623 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
14624 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14625 /* Unmute DAC0~3 & spdif out*/
14626 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14627 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14628 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14629 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14630 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14631 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14632 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14633 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14634 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14635 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014636
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014637 /* Unmute Stereo Mixer 15 */
14638 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14639 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14640 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014641 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014642
14643 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14644 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14645 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14646 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14647 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14648 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14649 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14650 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014651 /* hp used DAC 3 (Front) */
14652 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014653 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14654 { }
14655};
14656
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010014657/* additional init verbs for ASUS laptops */
14658static struct hda_verb alc861_asus_laptop_init_verbs[] = {
14659 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
14660 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
14661 { }
14662};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014663
Kailang Yangdf694da2005-12-05 19:42:22 +010014664/*
14665 * generic initialization of ADC, input mixers and output mixers
14666 */
14667static struct hda_verb alc861_auto_init_verbs[] = {
14668 /*
14669 * Unmute ADC0 and set the default input to mic-in
14670 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014671 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
Kailang Yangdf694da2005-12-05 19:42:22 +010014672 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014673
Kailang Yangdf694da2005-12-05 19:42:22 +010014674 /* Unmute DAC0~3 & spdif out*/
14675 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14676 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14677 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14678 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
14679 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020014680
Kailang Yangdf694da2005-12-05 19:42:22 +010014681 /* Unmute Mixer 14 (mic) 1c (Line in)*/
14682 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14683 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14684 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14685 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020014686
Kailang Yangdf694da2005-12-05 19:42:22 +010014687 /* Unmute Stereo Mixer 15 */
14688 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14689 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14690 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
14691 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
14692
Takashi Iwai1c209302009-07-22 15:17:45 +020014693 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14694 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
14695 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14696 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
14697 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14698 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
14699 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14700 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014701
14702 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14703 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai1c209302009-07-22 15:17:45 +020014704 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
14705 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014706 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
14707 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai1c209302009-07-22 15:17:45 +020014708 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
14709 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010014710
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014711 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */
Kailang Yangdf694da2005-12-05 19:42:22 +010014712
14713 { }
14714};
14715
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014716static struct hda_verb alc861_toshiba_init_verbs[] = {
14717 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014718
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014719 { }
14720};
14721
14722/* toggle speaker-output according to the hp-jack state */
14723static void alc861_toshiba_automute(struct hda_codec *codec)
14724{
Wu Fengguang864f92b2009-11-18 12:38:02 +080014725 unsigned int present = snd_hda_jack_detect(codec, 0x0f);
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014726
Takashi Iwai47fd8302007-08-10 17:11:07 +020014727 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
14728 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
14729 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
14730 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014731}
14732
14733static void alc861_toshiba_unsol_event(struct hda_codec *codec,
14734 unsigned int res)
14735{
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014736 if ((res >> 26) == ALC880_HP_EVENT)
14737 alc861_toshiba_automute(codec);
14738}
14739
Sasha Alexandrdef319f2009-06-16 16:00:15 -040014740/* pcm configuration: identical with ALC880 */
Kailang Yangdf694da2005-12-05 19:42:22 +010014741#define alc861_pcm_analog_playback alc880_pcm_analog_playback
14742#define alc861_pcm_analog_capture alc880_pcm_analog_capture
14743#define alc861_pcm_digital_playback alc880_pcm_digital_playback
14744#define alc861_pcm_digital_capture alc880_pcm_digital_capture
14745
14746
14747#define ALC861_DIGOUT_NID 0x07
14748
14749static struct hda_channel_mode alc861_8ch_modes[1] = {
14750 { 8, NULL }
14751};
14752
14753static hda_nid_t alc861_dac_nids[4] = {
14754 /* front, surround, clfe, side */
14755 0x03, 0x06, 0x05, 0x04
14756};
14757
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014758static hda_nid_t alc660_dac_nids[3] = {
14759 /* front, clfe, surround */
14760 0x03, 0x05, 0x06
14761};
14762
Kailang Yangdf694da2005-12-05 19:42:22 +010014763static hda_nid_t alc861_adc_nids[1] = {
14764 /* ADC0-2 */
14765 0x08,
14766};
14767
14768static struct hda_input_mux alc861_capture_source = {
14769 .num_items = 5,
14770 .items = {
14771 { "Mic", 0x0 },
14772 { "Front Mic", 0x3 },
14773 { "Line", 0x1 },
14774 { "CD", 0x4 },
14775 { "Mixer", 0x5 },
14776 },
14777};
14778
Takashi Iwai1c209302009-07-22 15:17:45 +020014779static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
14780{
14781 struct alc_spec *spec = codec->spec;
14782 hda_nid_t mix, srcs[5];
14783 int i, j, num;
14784
14785 if (snd_hda_get_connections(codec, pin, &mix, 1) != 1)
14786 return 0;
14787 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
14788 if (num < 0)
14789 return 0;
14790 for (i = 0; i < num; i++) {
14791 unsigned int type;
Takashi Iwaia22d5432009-07-27 12:54:26 +020014792 type = get_wcaps_type(get_wcaps(codec, srcs[i]));
Takashi Iwai1c209302009-07-22 15:17:45 +020014793 if (type != AC_WID_AUD_OUT)
14794 continue;
14795 for (j = 0; j < spec->multiout.num_dacs; j++)
14796 if (spec->multiout.dac_nids[j] == srcs[i])
14797 break;
14798 if (j >= spec->multiout.num_dacs)
14799 return srcs[i];
14800 }
14801 return 0;
14802}
14803
Kailang Yangdf694da2005-12-05 19:42:22 +010014804/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai1c209302009-07-22 15:17:45 +020014805static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014806 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010014807{
Takashi Iwai1c209302009-07-22 15:17:45 +020014808 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010014809 int i;
Takashi Iwai1c209302009-07-22 15:17:45 +020014810 hda_nid_t nid, dac;
Kailang Yangdf694da2005-12-05 19:42:22 +010014811
14812 spec->multiout.dac_nids = spec->private_dac_nids;
14813 for (i = 0; i < cfg->line_outs; i++) {
14814 nid = cfg->line_out_pins[i];
Takashi Iwai1c209302009-07-22 15:17:45 +020014815 dac = alc861_look_for_dac(codec, nid);
14816 if (!dac)
14817 continue;
14818 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
Kailang Yangdf694da2005-12-05 19:42:22 +010014819 }
Kailang Yangdf694da2005-12-05 19:42:22 +010014820 return 0;
14821}
14822
Takashi Iwai1c209302009-07-22 15:17:45 +020014823static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
14824 hda_nid_t nid, unsigned int chs)
Kailang Yangdf694da2005-12-05 19:42:22 +010014825{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020014826 return add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai1c209302009-07-22 15:17:45 +020014827 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
14828}
14829
14830/* add playback controls from the parsed DAC table */
14831static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
14832 const struct auto_pin_cfg *cfg)
14833{
14834 struct alc_spec *spec = codec->spec;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014835 static const char *chname[4] = {
14836 "Front", "Surround", NULL /*CLFE*/, "Side"
14837 };
Kailang Yangdf694da2005-12-05 19:42:22 +010014838 hda_nid_t nid;
Takashi Iwai1c209302009-07-22 15:17:45 +020014839 int i, err;
14840
14841 if (cfg->line_outs == 1) {
14842 const char *pfx = NULL;
14843 if (!cfg->hp_outs)
14844 pfx = "Master";
14845 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
14846 pfx = "Speaker";
14847 if (pfx) {
14848 nid = spec->multiout.dac_nids[0];
14849 return alc861_create_out_sw(codec, pfx, nid, 3);
14850 }
14851 }
Kailang Yangdf694da2005-12-05 19:42:22 +010014852
14853 for (i = 0; i < cfg->line_outs; i++) {
14854 nid = spec->multiout.dac_nids[i];
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014855 if (!nid)
Kailang Yangdf694da2005-12-05 19:42:22 +010014856 continue;
Takashi Iwai1c209302009-07-22 15:17:45 +020014857 if (i == 2) {
Kailang Yangdf694da2005-12-05 19:42:22 +010014858 /* Center/LFE */
Takashi Iwai1c209302009-07-22 15:17:45 +020014859 err = alc861_create_out_sw(codec, "Center", nid, 1);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014860 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010014861 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020014862 err = alc861_create_out_sw(codec, "LFE", nid, 2);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014863 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010014864 return err;
14865 } else {
Takashi Iwai1c209302009-07-22 15:17:45 +020014866 err = alc861_create_out_sw(codec, chname[i], nid, 3);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014867 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010014868 return err;
14869 }
14870 }
14871 return 0;
14872}
14873
Takashi Iwai1c209302009-07-22 15:17:45 +020014874static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
Kailang Yangdf694da2005-12-05 19:42:22 +010014875{
Takashi Iwai1c209302009-07-22 15:17:45 +020014876 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010014877 int err;
14878 hda_nid_t nid;
14879
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014880 if (!pin)
Kailang Yangdf694da2005-12-05 19:42:22 +010014881 return 0;
14882
14883 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
Takashi Iwai1c209302009-07-22 15:17:45 +020014884 nid = alc861_look_for_dac(codec, pin);
14885 if (nid) {
14886 err = alc861_create_out_sw(codec, "Headphone", nid, 3);
14887 if (err < 0)
14888 return err;
14889 spec->multiout.hp_nid = nid;
14890 }
Kailang Yangdf694da2005-12-05 19:42:22 +010014891 }
14892 return 0;
14893}
14894
14895/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020014896static int alc861_auto_create_input_ctls(struct hda_codec *codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014897 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010014898{
Takashi Iwai05f5f472009-08-25 13:10:18 +020014899 return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x08, 0);
Kailang Yangdf694da2005-12-05 19:42:22 +010014900}
14901
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014902static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
14903 hda_nid_t nid,
Takashi Iwai1c209302009-07-22 15:17:45 +020014904 int pin_type, hda_nid_t dac)
Kailang Yangdf694da2005-12-05 19:42:22 +010014905{
Takashi Iwai1c209302009-07-22 15:17:45 +020014906 hda_nid_t mix, srcs[5];
14907 int i, num;
14908
Jacek Luczak564c5be2008-05-03 18:41:23 +020014909 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
14910 pin_type);
Takashi Iwai1c209302009-07-22 15:17:45 +020014911 snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Jacek Luczak564c5be2008-05-03 18:41:23 +020014912 AMP_OUT_UNMUTE);
Takashi Iwai1c209302009-07-22 15:17:45 +020014913 if (snd_hda_get_connections(codec, nid, &mix, 1) != 1)
14914 return;
14915 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
14916 if (num < 0)
14917 return;
14918 for (i = 0; i < num; i++) {
14919 unsigned int mute;
14920 if (srcs[i] == dac || srcs[i] == 0x15)
14921 mute = AMP_IN_UNMUTE(i);
14922 else
14923 mute = AMP_IN_MUTE(i);
14924 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
14925 mute);
14926 }
Kailang Yangdf694da2005-12-05 19:42:22 +010014927}
14928
14929static void alc861_auto_init_multi_out(struct hda_codec *codec)
14930{
14931 struct alc_spec *spec = codec->spec;
14932 int i;
14933
14934 for (i = 0; i < spec->autocfg.line_outs; i++) {
14935 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020014936 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangdf694da2005-12-05 19:42:22 +010014937 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020014938 alc861_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014939 spec->multiout.dac_nids[i]);
Kailang Yangdf694da2005-12-05 19:42:22 +010014940 }
14941}
14942
14943static void alc861_auto_init_hp_out(struct hda_codec *codec)
14944{
14945 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010014946
Takashi Iwai15870f02009-10-05 08:25:13 +020014947 if (spec->autocfg.hp_outs)
14948 alc861_auto_set_output_and_unmute(codec,
14949 spec->autocfg.hp_pins[0],
14950 PIN_HP,
Takashi Iwai1c209302009-07-22 15:17:45 +020014951 spec->multiout.hp_nid);
Takashi Iwai15870f02009-10-05 08:25:13 +020014952 if (spec->autocfg.speaker_outs)
14953 alc861_auto_set_output_and_unmute(codec,
14954 spec->autocfg.speaker_pins[0],
14955 PIN_OUT,
Takashi Iwai1c209302009-07-22 15:17:45 +020014956 spec->multiout.dac_nids[0]);
Kailang Yangdf694da2005-12-05 19:42:22 +010014957}
14958
14959static void alc861_auto_init_analog_input(struct hda_codec *codec)
14960{
14961 struct alc_spec *spec = codec->spec;
14962 int i;
14963
14964 for (i = 0; i < AUTO_PIN_LAST; i++) {
14965 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai23f0c042009-02-26 13:03:58 +010014966 if (nid >= 0x0c && nid <= 0x11)
14967 alc_set_input_pin(codec, nid, i);
Kailang Yangdf694da2005-12-05 19:42:22 +010014968 }
14969}
14970
14971/* parse the BIOS configuration and set up the alc_spec */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014972/* return 1 if successful, 0 if the proper config is not found,
14973 * or a negative error code
14974 */
Kailang Yangdf694da2005-12-05 19:42:22 +010014975static int alc861_parse_auto_config(struct hda_codec *codec)
14976{
14977 struct alc_spec *spec = codec->spec;
14978 int err;
14979 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
14980
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014981 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
14982 alc861_ignore);
14983 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010014984 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014985 if (!spec->autocfg.line_outs)
Kailang Yangdf694da2005-12-05 19:42:22 +010014986 return 0; /* can't find valid BIOS pin config */
14987
Takashi Iwai1c209302009-07-22 15:17:45 +020014988 err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014989 if (err < 0)
14990 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020014991 err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014992 if (err < 0)
14993 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020014994 err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014995 if (err < 0)
14996 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020014997 err = alc861_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014998 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010014999 return err;
15000
15001 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
15002
Takashi Iwai0852d7a2009-02-11 11:35:15 +010015003 if (spec->autocfg.dig_outs)
Kailang Yangdf694da2005-12-05 19:42:22 +010015004 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
15005
Takashi Iwai603c4012008-07-30 15:01:44 +020015006 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010015007 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +010015008
Takashi Iwaid88897e2008-10-31 15:01:37 +010015009 add_verb(spec, alc861_auto_init_verbs);
Kailang Yangdf694da2005-12-05 19:42:22 +010015010
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +020015011 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020015012 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +010015013
15014 spec->adc_nids = alc861_adc_nids;
15015 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
Takashi Iwaib59bdf32009-08-11 09:47:30 +020015016 set_capture_mixer(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010015017
Kailang Yang6227cdc2010-02-25 08:36:52 +010015018 alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020015019
Kailang Yangdf694da2005-12-05 19:42:22 +010015020 return 1;
15021}
15022
Takashi Iwaiae6b8132006-03-03 16:47:17 +010015023/* additional initialization for auto-configuration model */
15024static void alc861_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +010015025{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010015026 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015027 alc861_auto_init_multi_out(codec);
15028 alc861_auto_init_hp_out(codec);
15029 alc861_auto_init_analog_input(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010015030 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020015031 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010015032}
15033
Takashi Iwaicb53c622007-08-10 17:21:45 +020015034#ifdef CONFIG_SND_HDA_POWER_SAVE
15035static struct hda_amp_list alc861_loopbacks[] = {
15036 { 0x15, HDA_INPUT, 0 },
15037 { 0x15, HDA_INPUT, 1 },
15038 { 0x15, HDA_INPUT, 2 },
15039 { 0x15, HDA_INPUT, 3 },
15040 { } /* end */
15041};
15042#endif
15043
Kailang Yangdf694da2005-12-05 19:42:22 +010015044
15045/*
15046 * configuration and preset
15047 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015048static const char *alc861_models[ALC861_MODEL_LAST] = {
15049 [ALC861_3ST] = "3stack",
15050 [ALC660_3ST] = "3stack-660",
15051 [ALC861_3ST_DIG] = "3stack-dig",
15052 [ALC861_6ST_DIG] = "6stack-dig",
15053 [ALC861_UNIWILL_M31] = "uniwill-m31",
15054 [ALC861_TOSHIBA] = "toshiba",
15055 [ALC861_ASUS] = "asus",
15056 [ALC861_ASUS_LAPTOP] = "asus-laptop",
15057 [ALC861_AUTO] = "auto",
15058};
15059
15060static struct snd_pci_quirk alc861_cfg_tbl[] = {
Takashi Iwai687a47b2007-01-10 11:25:58 +010015061 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015062 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
15063 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
15064 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015065 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
Kailang Yang83c34212007-07-05 11:43:05 +020015066 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
Tobin Davisad5e7732007-01-08 10:57:32 +010015067 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
Takashi Iwai341d4eb2007-07-09 17:53:18 +020015068 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
15069 * Any other models that need this preset?
15070 */
15071 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
Claudio Matsuokaef64adb2007-07-14 00:26:16 +020015072 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
15073 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015074 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
15075 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
15076 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
15077 /* FIXME: the below seems conflict */
15078 /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
15079 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
15080 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
Kailang Yangdf694da2005-12-05 19:42:22 +010015081 {}
15082};
15083
15084static struct alc_config_preset alc861_presets[] = {
15085 [ALC861_3ST] = {
15086 .mixers = { alc861_3ST_mixer },
15087 .init_verbs = { alc861_threestack_init_verbs },
15088 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15089 .dac_nids = alc861_dac_nids,
15090 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15091 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015092 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +010015093 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15094 .adc_nids = alc861_adc_nids,
15095 .input_mux = &alc861_capture_source,
15096 },
15097 [ALC861_3ST_DIG] = {
15098 .mixers = { alc861_base_mixer },
15099 .init_verbs = { alc861_threestack_init_verbs },
15100 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15101 .dac_nids = alc861_dac_nids,
15102 .dig_out_nid = ALC861_DIGOUT_NID,
15103 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15104 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015105 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +010015106 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15107 .adc_nids = alc861_adc_nids,
15108 .input_mux = &alc861_capture_source,
15109 },
15110 [ALC861_6ST_DIG] = {
15111 .mixers = { alc861_base_mixer },
15112 .init_verbs = { alc861_base_init_verbs },
15113 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15114 .dac_nids = alc861_dac_nids,
15115 .dig_out_nid = ALC861_DIGOUT_NID,
15116 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
15117 .channel_mode = alc861_8ch_modes,
15118 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15119 .adc_nids = alc861_adc_nids,
15120 .input_mux = &alc861_capture_source,
15121 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015122 [ALC660_3ST] = {
15123 .mixers = { alc861_3ST_mixer },
15124 .init_verbs = { alc861_threestack_init_verbs },
15125 .num_dacs = ARRAY_SIZE(alc660_dac_nids),
15126 .dac_nids = alc660_dac_nids,
15127 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15128 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015129 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015130 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15131 .adc_nids = alc861_adc_nids,
15132 .input_mux = &alc861_capture_source,
15133 },
Takashi Iwai22309c32006-08-09 16:57:28 +020015134 [ALC861_UNIWILL_M31] = {
15135 .mixers = { alc861_uniwill_m31_mixer },
15136 .init_verbs = { alc861_uniwill_m31_init_verbs },
15137 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15138 .dac_nids = alc861_dac_nids,
15139 .dig_out_nid = ALC861_DIGOUT_NID,
15140 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
15141 .channel_mode = alc861_uniwill_m31_modes,
15142 .need_dac_fix = 1,
15143 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15144 .adc_nids = alc861_adc_nids,
15145 .input_mux = &alc861_capture_source,
15146 },
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015147 [ALC861_TOSHIBA] = {
15148 .mixers = { alc861_toshiba_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015149 .init_verbs = { alc861_base_init_verbs,
15150 alc861_toshiba_init_verbs },
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015151 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15152 .dac_nids = alc861_dac_nids,
15153 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
15154 .channel_mode = alc883_3ST_2ch_modes,
15155 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15156 .adc_nids = alc861_adc_nids,
15157 .input_mux = &alc861_capture_source,
15158 .unsol_event = alc861_toshiba_unsol_event,
15159 .init_hook = alc861_toshiba_automute,
15160 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015161 [ALC861_ASUS] = {
15162 .mixers = { alc861_asus_mixer },
15163 .init_verbs = { alc861_asus_init_verbs },
15164 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15165 .dac_nids = alc861_dac_nids,
15166 .dig_out_nid = ALC861_DIGOUT_NID,
15167 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
15168 .channel_mode = alc861_asus_modes,
15169 .need_dac_fix = 1,
15170 .hp_nid = 0x06,
15171 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15172 .adc_nids = alc861_adc_nids,
15173 .input_mux = &alc861_capture_source,
15174 },
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010015175 [ALC861_ASUS_LAPTOP] = {
15176 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
15177 .init_verbs = { alc861_asus_init_verbs,
15178 alc861_asus_laptop_init_verbs },
15179 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15180 .dac_nids = alc861_dac_nids,
15181 .dig_out_nid = ALC861_DIGOUT_NID,
15182 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
15183 .channel_mode = alc883_3ST_2ch_modes,
15184 .need_dac_fix = 1,
15185 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15186 .adc_nids = alc861_adc_nids,
15187 .input_mux = &alc861_capture_source,
15188 },
15189};
Kailang Yangdf694da2005-12-05 19:42:22 +010015190
Takashi Iwaicfc9b062009-12-01 12:19:37 +010015191/* Pin config fixes */
15192enum {
15193 PINFIX_FSC_AMILO_PI1505,
15194};
15195
15196static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = {
15197 { 0x0b, 0x0221101f }, /* HP */
15198 { 0x0f, 0x90170310 }, /* speaker */
15199 { }
15200};
15201
15202static const struct alc_fixup alc861_fixups[] = {
15203 [PINFIX_FSC_AMILO_PI1505] = {
15204 .pins = alc861_fsc_amilo_pi1505_pinfix
15205 },
15206};
15207
15208static struct snd_pci_quirk alc861_fixup_tbl[] = {
15209 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
15210 {}
15211};
Kailang Yangdf694da2005-12-05 19:42:22 +010015212
15213static int patch_alc861(struct hda_codec *codec)
15214{
15215 struct alc_spec *spec;
15216 int board_config;
15217 int err;
15218
Robert P. J. Daydc041e02006-12-19 14:44:15 +010015219 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yangdf694da2005-12-05 19:42:22 +010015220 if (spec == NULL)
15221 return -ENOMEM;
15222
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015223 codec->spec = spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015224
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015225 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
15226 alc861_models,
15227 alc861_cfg_tbl);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015228
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015229 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020015230 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
15231 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +010015232 board_config = ALC861_AUTO;
15233 }
15234
Takashi Iwaicfc9b062009-12-01 12:19:37 +010015235 alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups);
15236
Kailang Yangdf694da2005-12-05 19:42:22 +010015237 if (board_config == ALC861_AUTO) {
15238 /* automatic parse from the BIOS config */
15239 err = alc861_parse_auto_config(codec);
15240 if (err < 0) {
15241 alc_free(codec);
15242 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015243 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015244 printk(KERN_INFO
15245 "hda_codec: Cannot set up configuration "
15246 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +010015247 board_config = ALC861_3ST_DIG;
15248 }
15249 }
15250
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090015251 err = snd_hda_attach_beep_device(codec, 0x23);
15252 if (err < 0) {
15253 alc_free(codec);
15254 return err;
15255 }
15256
Kailang Yangdf694da2005-12-05 19:42:22 +010015257 if (board_config != ALC861_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020015258 setup_preset(codec, &alc861_presets[board_config]);
Kailang Yangdf694da2005-12-05 19:42:22 +010015259
Kailang Yangdf694da2005-12-05 19:42:22 +010015260 spec->stream_analog_playback = &alc861_pcm_analog_playback;
15261 spec->stream_analog_capture = &alc861_pcm_analog_capture;
15262
Kailang Yangdf694da2005-12-05 19:42:22 +010015263 spec->stream_digital_playback = &alc861_pcm_digital_playback;
15264 spec->stream_digital_capture = &alc861_pcm_digital_capture;
15265
Takashi Iwaic7a8eb12010-01-14 12:39:02 +010015266 if (!spec->cap_mixer)
15267 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010015268 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
15269
Takashi Iwai2134ea42008-01-10 16:53:55 +010015270 spec->vmaster_nid = 0x03;
15271
Kailang Yangdf694da2005-12-05 19:42:22 +010015272 codec->patch_ops = alc_patch_ops;
Daniel T Chenc97259d2009-12-27 18:52:08 -050015273 if (board_config == ALC861_AUTO) {
Takashi Iwaiae6b8132006-03-03 16:47:17 +010015274 spec->init_hook = alc861_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020015275#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -050015276 spec->power_hook = alc_power_eapd;
15277#endif
15278 }
15279#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaicb53c622007-08-10 17:21:45 +020015280 if (!spec->loopback.amplist)
15281 spec->loopback.amplist = alc861_loopbacks;
15282#endif
Kailang Yangea1fb292008-08-26 12:58:38 +020015283
Kailang Yangdf694da2005-12-05 19:42:22 +010015284 return 0;
15285}
15286
15287/*
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015288 * ALC861-VD support
15289 *
15290 * Based on ALC882
15291 *
15292 * In addition, an independent DAC
15293 */
15294#define ALC861VD_DIGOUT_NID 0x06
15295
15296static hda_nid_t alc861vd_dac_nids[4] = {
15297 /* front, surr, clfe, side surr */
15298 0x02, 0x03, 0x04, 0x05
15299};
15300
15301/* dac_nids for ALC660vd are in a different order - according to
15302 * Realtek's driver.
Sasha Alexandrdef319f2009-06-16 16:00:15 -040015303 * This should probably result in a different mixer for 6stack models
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015304 * of ALC660vd codecs, but for now there is only 3stack mixer
15305 * - and it is the same as in 861vd.
15306 * adc_nids in ALC660vd are (is) the same as in 861vd
15307 */
15308static hda_nid_t alc660vd_dac_nids[3] = {
15309 /* front, rear, clfe, rear_surr */
15310 0x02, 0x04, 0x03
15311};
15312
15313static hda_nid_t alc861vd_adc_nids[1] = {
15314 /* ADC0 */
15315 0x09,
15316};
15317
Takashi Iwaie1406342008-02-11 18:32:32 +010015318static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
15319
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015320/* input MUX */
15321/* FIXME: should be a matrix-type input source selection */
15322static struct hda_input_mux alc861vd_capture_source = {
15323 .num_items = 4,
15324 .items = {
15325 { "Mic", 0x0 },
15326 { "Front Mic", 0x1 },
15327 { "Line", 0x2 },
15328 { "CD", 0x4 },
15329 },
15330};
15331
Kailang Yang272a5272007-05-14 11:00:38 +020015332static struct hda_input_mux alc861vd_dallas_capture_source = {
Tobin Davisb419f342008-03-07 11:57:51 +010015333 .num_items = 2,
Kailang Yang272a5272007-05-14 11:00:38 +020015334 .items = {
Tobin Davisb419f342008-03-07 11:57:51 +010015335 { "Ext Mic", 0x0 },
15336 { "Int Mic", 0x1 },
Kailang Yang272a5272007-05-14 11:00:38 +020015337 },
15338};
15339
Kailang Yangd1a991a2007-08-15 16:21:59 +020015340static struct hda_input_mux alc861vd_hp_capture_source = {
15341 .num_items = 2,
15342 .items = {
15343 { "Front Mic", 0x0 },
15344 { "ATAPI Mic", 0x1 },
15345 },
15346};
15347
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015348/*
15349 * 2ch mode
15350 */
15351static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
15352 { 2, NULL }
15353};
15354
15355/*
15356 * 6ch mode
15357 */
15358static struct hda_verb alc861vd_6stack_ch6_init[] = {
15359 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15360 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15361 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15362 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15363 { } /* end */
15364};
15365
15366/*
15367 * 8ch mode
15368 */
15369static struct hda_verb alc861vd_6stack_ch8_init[] = {
15370 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15371 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15372 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15373 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15374 { } /* end */
15375};
15376
15377static struct hda_channel_mode alc861vd_6stack_modes[2] = {
15378 { 6, alc861vd_6stack_ch6_init },
15379 { 8, alc861vd_6stack_ch8_init },
15380};
15381
15382static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
15383 {
15384 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15385 .name = "Channel Mode",
15386 .info = alc_ch_mode_info,
15387 .get = alc_ch_mode_get,
15388 .put = alc_ch_mode_put,
15389 },
15390 { } /* end */
15391};
15392
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015393/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
15394 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
15395 */
15396static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
15397 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15398 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
15399
15400 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
15401 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
15402
15403 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
15404 HDA_OUTPUT),
15405 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
15406 HDA_OUTPUT),
15407 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
15408 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
15409
15410 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
15411 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
15412
15413 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
15414
15415 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
15416 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15417 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15418
15419 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
15420 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15421 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
15422
15423 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
15424 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
15425
15426 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
15427 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
15428
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015429 { } /* end */
15430};
15431
15432static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
15433 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15434 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
15435
15436 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
15437
15438 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
15439 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15440 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15441
15442 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
15443 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15444 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
15445
15446 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
15447 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
15448
15449 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
15450 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
15451
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015452 { } /* end */
15453};
15454
Kailang Yangbdd148a2007-05-08 15:19:08 +020015455static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
15456 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15457 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
15458 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
15459
15460 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
15461
15462 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
15463 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15464 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15465
15466 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
15467 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15468 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
15469
15470 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
15471 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
15472
15473 { } /* end */
15474};
15475
Tobin Davisb419f342008-03-07 11:57:51 +010015476/* Pin assignment: Speaker=0x14, HP = 0x15,
15477 * Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
Kailang Yang272a5272007-05-14 11:00:38 +020015478 */
15479static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
Tobin Davisb419f342008-03-07 11:57:51 +010015480 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15481 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +020015482 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
15483 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
Tobin Davisb419f342008-03-07 11:57:51 +010015484 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
15485 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15486 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15487 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
15488 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15489 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +020015490 { } /* end */
15491};
15492
Kailang Yangd1a991a2007-08-15 16:21:59 +020015493/* Pin assignment: Speaker=0x14, Line-out = 0x15,
15494 * Front Mic=0x18, ATAPI Mic = 0x19,
15495 */
15496static struct snd_kcontrol_new alc861vd_hp_mixer[] = {
15497 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
15498 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
15499 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
15500 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
15501 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
15502 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
15503 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
15504 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangea1fb292008-08-26 12:58:38 +020015505
Kailang Yangd1a991a2007-08-15 16:21:59 +020015506 { } /* end */
15507};
15508
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015509/*
15510 * generic initialization of ADC, input mixers and output mixers
15511 */
15512static struct hda_verb alc861vd_volume_init_verbs[] = {
15513 /*
15514 * Unmute ADC0 and set the default input to mic-in
15515 */
15516 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
15517 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15518
15519 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
15520 * the analog-loopback mixer widget
15521 */
15522 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020015523 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15524 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15525 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15526 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
15527 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015528
15529 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
Kailang Yangbdd148a2007-05-08 15:19:08 +020015530 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15531 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15532 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015533 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015534
15535 /*
15536 * Set up output mixers (0x02 - 0x05)
15537 */
15538 /* set vol=0 to output mixers */
15539 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15540 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15541 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15542 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15543
15544 /* set up input amps for analog loopback */
15545 /* Amp Indices: DAC = 0, mixer = 1 */
15546 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15547 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15548 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15549 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15550 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15551 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15552 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15553 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15554
15555 { }
15556};
15557
15558/*
15559 * 3-stack pin configuration:
15560 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
15561 */
15562static struct hda_verb alc861vd_3stack_init_verbs[] = {
15563 /*
15564 * Set pin mode and muting
15565 */
15566 /* set front pin widgets 0x14 for output */
15567 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15568 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15569 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
15570
15571 /* Mic (rear) pin: input vref at 80% */
15572 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
15573 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15574 /* Front Mic pin: input vref at 80% */
15575 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
15576 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15577 /* Line In pin: input */
15578 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15579 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15580 /* Line-2 In: Headphone output (output 0 - 0x0c) */
15581 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
15582 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15583 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
15584 /* CD pin widget for input */
15585 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15586
15587 { }
15588};
15589
15590/*
15591 * 6-stack pin configuration:
15592 */
15593static struct hda_verb alc861vd_6stack_init_verbs[] = {
15594 /*
15595 * Set pin mode and muting
15596 */
15597 /* set front pin widgets 0x14 for output */
15598 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15599 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15600 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
15601
15602 /* Rear Pin: output 1 (0x0d) */
15603 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15604 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15605 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
15606 /* CLFE Pin: output 2 (0x0e) */
15607 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15608 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15609 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
15610 /* Side Pin: output 3 (0x0f) */
15611 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15612 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15613 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
15614
15615 /* Mic (rear) pin: input vref at 80% */
15616 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
15617 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15618 /* Front Mic pin: input vref at 80% */
15619 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
15620 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15621 /* Line In pin: input */
15622 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15623 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15624 /* Line-2 In: Headphone output (output 0 - 0x0c) */
15625 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
15626 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15627 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
15628 /* CD pin widget for input */
15629 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15630
15631 { }
15632};
15633
Kailang Yangbdd148a2007-05-08 15:19:08 +020015634static struct hda_verb alc861vd_eapd_verbs[] = {
15635 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
15636 { }
15637};
15638
Kailang Yangf9423e72008-05-27 12:32:25 +020015639static struct hda_verb alc660vd_eapd_verbs[] = {
15640 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
15641 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
15642 { }
15643};
15644
Kailang Yangbdd148a2007-05-08 15:19:08 +020015645static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
15646 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15647 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15648 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
15649 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Kailang Yangea1fb292008-08-26 12:58:38 +020015650 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
Kailang Yangbdd148a2007-05-08 15:19:08 +020015651 {}
15652};
15653
Kailang Yangbdd148a2007-05-08 15:19:08 +020015654static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
15655{
15656 unsigned int present;
15657 unsigned char bits;
15658
Wu Fengguang864f92b2009-11-18 12:38:02 +080015659 present = snd_hda_jack_detect(codec, 0x18);
Takashi Iwai47fd8302007-08-10 17:11:07 +020015660 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080015661
Takashi Iwai47fd8302007-08-10 17:11:07 +020015662 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
15663 HDA_AMP_MUTE, bits);
Kailang Yangbdd148a2007-05-08 15:19:08 +020015664}
15665
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015666static void alc861vd_lenovo_setup(struct hda_codec *codec)
Kailang Yangbdd148a2007-05-08 15:19:08 +020015667{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015668 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015669 spec->autocfg.hp_pins[0] = 0x1b;
15670 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015671}
15672
15673static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
15674{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015675 alc_automute_amp(codec);
Kailang Yangbdd148a2007-05-08 15:19:08 +020015676 alc861vd_lenovo_mic_automute(codec);
15677}
15678
15679static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
15680 unsigned int res)
15681{
15682 switch (res >> 26) {
Kailang Yangbdd148a2007-05-08 15:19:08 +020015683 case ALC880_MIC_EVENT:
15684 alc861vd_lenovo_mic_automute(codec);
15685 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015686 default:
15687 alc_automute_amp_unsol_event(codec, res);
15688 break;
Kailang Yangbdd148a2007-05-08 15:19:08 +020015689 }
15690}
15691
Kailang Yang272a5272007-05-14 11:00:38 +020015692static struct hda_verb alc861vd_dallas_verbs[] = {
15693 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15694 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15695 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15696 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
15697
15698 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15699 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15700 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15701 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15702 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15703 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15704 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15705 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015706
Kailang Yang272a5272007-05-14 11:00:38 +020015707 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15708 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15709 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15710 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15711 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15712 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15713 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
15714 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15715
15716 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
15717 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15718 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
15719 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15720 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15721 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15722 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15723 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
15724
15725 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15726 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
15727 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15728 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
15729
15730 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015731 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yang272a5272007-05-14 11:00:38 +020015732 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
15733
15734 { } /* end */
15735};
15736
15737/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015738static void alc861vd_dallas_setup(struct hda_codec *codec)
Kailang Yang272a5272007-05-14 11:00:38 +020015739{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015740 struct alc_spec *spec = codec->spec;
Kailang Yang272a5272007-05-14 11:00:38 +020015741
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015742 spec->autocfg.hp_pins[0] = 0x15;
15743 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang272a5272007-05-14 11:00:38 +020015744}
15745
Takashi Iwaicb53c622007-08-10 17:21:45 +020015746#ifdef CONFIG_SND_HDA_POWER_SAVE
15747#define alc861vd_loopbacks alc880_loopbacks
15748#endif
15749
Sasha Alexandrdef319f2009-06-16 16:00:15 -040015750/* pcm configuration: identical with ALC880 */
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015751#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
15752#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
15753#define alc861vd_pcm_digital_playback alc880_pcm_digital_playback
15754#define alc861vd_pcm_digital_capture alc880_pcm_digital_capture
15755
15756/*
15757 * configuration and preset
15758 */
15759static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
15760 [ALC660VD_3ST] = "3stack-660",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020015761 [ALC660VD_3ST_DIG] = "3stack-660-digout",
Takashi Iwai13c94742008-11-05 08:06:08 +010015762 [ALC660VD_ASUS_V1S] = "asus-v1s",
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015763 [ALC861VD_3ST] = "3stack",
15764 [ALC861VD_3ST_DIG] = "3stack-digout",
15765 [ALC861VD_6ST_DIG] = "6stack-digout",
Kailang Yangbdd148a2007-05-08 15:19:08 +020015766 [ALC861VD_LENOVO] = "lenovo",
Kailang Yang272a5272007-05-14 11:00:38 +020015767 [ALC861VD_DALLAS] = "dallas",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020015768 [ALC861VD_HP] = "hp",
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015769 [ALC861VD_AUTO] = "auto",
15770};
15771
15772static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015773 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
15774 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
Takashi Iwai07e038b2007-02-15 18:23:41 +010015775 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020015776 /*SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),*/ /* auto */
Takashi Iwai13c94742008-11-05 08:06:08 +010015777 SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
Mike Crash6963f842007-06-25 12:12:51 +020015778 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015779 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015780 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
Takashi Iwai38baf5a2007-08-16 17:52:43 +020015781 /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
Takashi Iwaice577e82009-08-03 08:23:52 +020015782 SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
Takashi Iwai542d7c62007-08-16 18:57:30 +020015783 SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
Tobin Davisb419f342008-03-07 11:57:51 +010015784 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
Takashi Iwai39c5d412007-08-15 16:24:17 +020015785 SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +010015786 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
Tobin Davis625dc0b2007-07-30 21:42:10 +020015787 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015788 {}
15789};
15790
15791static struct alc_config_preset alc861vd_presets[] = {
15792 [ALC660VD_3ST] = {
15793 .mixers = { alc861vd_3st_mixer },
15794 .init_verbs = { alc861vd_volume_init_verbs,
15795 alc861vd_3stack_init_verbs },
15796 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
15797 .dac_nids = alc660vd_dac_nids,
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015798 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15799 .channel_mode = alc861vd_3stack_2ch_modes,
15800 .input_mux = &alc861vd_capture_source,
15801 },
Mike Crash6963f842007-06-25 12:12:51 +020015802 [ALC660VD_3ST_DIG] = {
15803 .mixers = { alc861vd_3st_mixer },
15804 .init_verbs = { alc861vd_volume_init_verbs,
15805 alc861vd_3stack_init_verbs },
15806 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
15807 .dac_nids = alc660vd_dac_nids,
15808 .dig_out_nid = ALC861VD_DIGOUT_NID,
Mike Crash6963f842007-06-25 12:12:51 +020015809 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15810 .channel_mode = alc861vd_3stack_2ch_modes,
15811 .input_mux = &alc861vd_capture_source,
15812 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015813 [ALC861VD_3ST] = {
15814 .mixers = { alc861vd_3st_mixer },
15815 .init_verbs = { alc861vd_volume_init_verbs,
15816 alc861vd_3stack_init_verbs },
15817 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
15818 .dac_nids = alc861vd_dac_nids,
15819 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15820 .channel_mode = alc861vd_3stack_2ch_modes,
15821 .input_mux = &alc861vd_capture_source,
15822 },
15823 [ALC861VD_3ST_DIG] = {
15824 .mixers = { alc861vd_3st_mixer },
15825 .init_verbs = { alc861vd_volume_init_verbs,
15826 alc861vd_3stack_init_verbs },
15827 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
15828 .dac_nids = alc861vd_dac_nids,
15829 .dig_out_nid = ALC861VD_DIGOUT_NID,
15830 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15831 .channel_mode = alc861vd_3stack_2ch_modes,
15832 .input_mux = &alc861vd_capture_source,
15833 },
15834 [ALC861VD_6ST_DIG] = {
15835 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
15836 .init_verbs = { alc861vd_volume_init_verbs,
15837 alc861vd_6stack_init_verbs },
15838 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
15839 .dac_nids = alc861vd_dac_nids,
15840 .dig_out_nid = ALC861VD_DIGOUT_NID,
15841 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
15842 .channel_mode = alc861vd_6stack_modes,
15843 .input_mux = &alc861vd_capture_source,
15844 },
Kailang Yangbdd148a2007-05-08 15:19:08 +020015845 [ALC861VD_LENOVO] = {
15846 .mixers = { alc861vd_lenovo_mixer },
15847 .init_verbs = { alc861vd_volume_init_verbs,
15848 alc861vd_3stack_init_verbs,
15849 alc861vd_eapd_verbs,
15850 alc861vd_lenovo_unsol_verbs },
15851 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
15852 .dac_nids = alc660vd_dac_nids,
Kailang Yangbdd148a2007-05-08 15:19:08 +020015853 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15854 .channel_mode = alc861vd_3stack_2ch_modes,
15855 .input_mux = &alc861vd_capture_source,
15856 .unsol_event = alc861vd_lenovo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015857 .setup = alc861vd_lenovo_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015858 .init_hook = alc861vd_lenovo_init_hook,
Kailang Yangbdd148a2007-05-08 15:19:08 +020015859 },
Kailang Yang272a5272007-05-14 11:00:38 +020015860 [ALC861VD_DALLAS] = {
15861 .mixers = { alc861vd_dallas_mixer },
15862 .init_verbs = { alc861vd_dallas_verbs },
15863 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
15864 .dac_nids = alc861vd_dac_nids,
Kailang Yang272a5272007-05-14 11:00:38 +020015865 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15866 .channel_mode = alc861vd_3stack_2ch_modes,
15867 .input_mux = &alc861vd_dallas_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015868 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015869 .setup = alc861vd_dallas_setup,
15870 .init_hook = alc_automute_amp,
Kailang Yangd1a991a2007-08-15 16:21:59 +020015871 },
15872 [ALC861VD_HP] = {
15873 .mixers = { alc861vd_hp_mixer },
15874 .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
15875 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
15876 .dac_nids = alc861vd_dac_nids,
Kailang Yangd1a991a2007-08-15 16:21:59 +020015877 .dig_out_nid = ALC861VD_DIGOUT_NID,
Kailang Yangd1a991a2007-08-15 16:21:59 +020015878 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15879 .channel_mode = alc861vd_3stack_2ch_modes,
15880 .input_mux = &alc861vd_hp_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015881 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015882 .setup = alc861vd_dallas_setup,
15883 .init_hook = alc_automute_amp,
Kailang Yangea1fb292008-08-26 12:58:38 +020015884 },
Takashi Iwai13c94742008-11-05 08:06:08 +010015885 [ALC660VD_ASUS_V1S] = {
15886 .mixers = { alc861vd_lenovo_mixer },
15887 .init_verbs = { alc861vd_volume_init_verbs,
15888 alc861vd_3stack_init_verbs,
15889 alc861vd_eapd_verbs,
15890 alc861vd_lenovo_unsol_verbs },
15891 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
15892 .dac_nids = alc660vd_dac_nids,
15893 .dig_out_nid = ALC861VD_DIGOUT_NID,
15894 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
15895 .channel_mode = alc861vd_3stack_2ch_modes,
15896 .input_mux = &alc861vd_capture_source,
15897 .unsol_event = alc861vd_lenovo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020015898 .setup = alc861vd_lenovo_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020015899 .init_hook = alc861vd_lenovo_init_hook,
Takashi Iwai13c94742008-11-05 08:06:08 +010015900 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015901};
15902
15903/*
15904 * BIOS auto configuration
15905 */
Takashi Iwai05f5f472009-08-25 13:10:18 +020015906static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
15907 const struct auto_pin_cfg *cfg)
15908{
Kailang Yang6227cdc2010-02-25 08:36:52 +010015909 return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
Takashi Iwai05f5f472009-08-25 13:10:18 +020015910}
15911
15912
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015913static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
15914 hda_nid_t nid, int pin_type, int dac_idx)
15915{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010015916 alc_set_pin_output(codec, nid, pin_type);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015917}
15918
15919static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
15920{
15921 struct alc_spec *spec = codec->spec;
15922 int i;
15923
15924 for (i = 0; i <= HDA_SIDE; i++) {
15925 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020015926 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015927 if (nid)
15928 alc861vd_auto_set_output_and_unmute(codec, nid,
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020015929 pin_type, i);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015930 }
15931}
15932
15933
15934static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
15935{
15936 struct alc_spec *spec = codec->spec;
15937 hda_nid_t pin;
15938
15939 pin = spec->autocfg.hp_pins[0];
Sasha Alexandrdef319f2009-06-16 16:00:15 -040015940 if (pin) /* connect to front and use dac 0 */
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015941 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010015942 pin = spec->autocfg.speaker_pins[0];
15943 if (pin)
15944 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015945}
15946
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015947#define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID
15948
15949static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
15950{
15951 struct alc_spec *spec = codec->spec;
15952 int i;
15953
15954 for (i = 0; i < AUTO_PIN_LAST; i++) {
15955 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai05f5f472009-08-25 13:10:18 +020015956 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +010015957 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +010015958 if (nid != ALC861VD_PIN_CD_NID &&
15959 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015960 snd_hda_codec_write(codec, nid, 0,
15961 AC_VERB_SET_AMP_GAIN_MUTE,
15962 AMP_OUT_MUTE);
15963 }
15964 }
15965}
15966
Takashi Iwaif511b012008-08-15 16:46:42 +020015967#define alc861vd_auto_init_input_src alc882_auto_init_input_src
15968
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015969#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)
15970#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)
15971
15972/* add playback controls from the parsed DAC table */
15973/* Based on ALC880 version. But ALC861VD has separate,
15974 * different NIDs for mute/unmute switch and volume control */
15975static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
15976 const struct auto_pin_cfg *cfg)
15977{
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015978 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
15979 hda_nid_t nid_v, nid_s;
15980 int i, err;
15981
15982 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015983 if (!spec->multiout.dac_nids[i])
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015984 continue;
15985 nid_v = alc861vd_idx_to_mixer_vol(
15986 alc880_dac_to_idx(
15987 spec->multiout.dac_nids[i]));
15988 nid_s = alc861vd_idx_to_mixer_switch(
15989 alc880_dac_to_idx(
15990 spec->multiout.dac_nids[i]));
15991
15992 if (i == 2) {
15993 /* Center/LFE */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020015994 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
15995 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015996 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
15997 HDA_OUTPUT));
15998 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015999 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016000 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
16001 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016002 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
16003 HDA_OUTPUT));
16004 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016005 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016006 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
16007 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016008 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
16009 HDA_INPUT));
16010 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016011 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016012 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
16013 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016014 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
16015 HDA_INPUT));
16016 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016017 return err;
16018 } else {
Takashi Iwaia4fcd492009-08-25 16:12:15 +020016019 const char *pfx;
16020 if (cfg->line_outs == 1 &&
16021 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
16022 if (!cfg->hp_pins)
16023 pfx = "Speaker";
16024 else
16025 pfx = "PCM";
16026 } else
16027 pfx = chname[i];
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016028 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016029 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
16030 HDA_OUTPUT));
16031 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016032 return err;
Takashi Iwaia4fcd492009-08-25 16:12:15 +020016033 if (cfg->line_outs == 1 &&
16034 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
16035 pfx = "Speaker";
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016036 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Kailang Yangbdd148a2007-05-08 15:19:08 +020016037 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016038 HDA_INPUT));
16039 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016040 return err;
16041 }
16042 }
16043 return 0;
16044}
16045
16046/* add playback controls for speaker and HP outputs */
16047/* Based on ALC880 version. But ALC861VD has separate,
16048 * different NIDs for mute/unmute switch and volume control */
16049static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
16050 hda_nid_t pin, const char *pfx)
16051{
16052 hda_nid_t nid_v, nid_s;
16053 int err;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016054
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016055 if (!pin)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016056 return 0;
16057
16058 if (alc880_is_fixed_pin(pin)) {
16059 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
16060 /* specify the DAC as the extra output */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016061 if (!spec->multiout.hp_nid)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016062 spec->multiout.hp_nid = nid_v;
16063 else
16064 spec->multiout.extra_out_nid[0] = nid_v;
16065 /* control HP volume/switch on the output mixer amp */
16066 nid_v = alc861vd_idx_to_mixer_vol(
16067 alc880_fixed_pin_idx(pin));
16068 nid_s = alc861vd_idx_to_mixer_switch(
16069 alc880_fixed_pin_idx(pin));
16070
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016071 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016072 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
16073 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016074 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016075 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016076 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
16077 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016078 return err;
16079 } else if (alc880_is_multi_pin(pin)) {
16080 /* set manual connection */
16081 /* we have only a switch on HP-out PIN */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016082 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016083 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
16084 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016085 return err;
16086 }
16087 return 0;
16088}
16089
16090/* parse the BIOS configuration and set up the alc_spec
16091 * return 1 if successful, 0 if the proper config is not found,
16092 * or a negative error code
16093 * Based on ALC880 version - had to change it to override
16094 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
16095static int alc861vd_parse_auto_config(struct hda_codec *codec)
16096{
16097 struct alc_spec *spec = codec->spec;
16098 int err;
16099 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
16100
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016101 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
16102 alc861vd_ignore);
16103 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016104 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016105 if (!spec->autocfg.line_outs)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016106 return 0; /* can't find valid BIOS pin config */
16107
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016108 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
16109 if (err < 0)
16110 return err;
16111 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
16112 if (err < 0)
16113 return err;
16114 err = alc861vd_auto_create_extra_out(spec,
16115 spec->autocfg.speaker_pins[0],
16116 "Speaker");
16117 if (err < 0)
16118 return err;
16119 err = alc861vd_auto_create_extra_out(spec,
16120 spec->autocfg.hp_pins[0],
16121 "Headphone");
16122 if (err < 0)
16123 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020016124 err = alc861vd_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016125 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016126 return err;
16127
16128 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
16129
Takashi Iwai0852d7a2009-02-11 11:35:15 +010016130 if (spec->autocfg.dig_outs)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016131 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
16132
Takashi Iwai603c4012008-07-30 15:01:44 +020016133 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010016134 add_mixer(spec, spec->kctls.list);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016135
Takashi Iwaid88897e2008-10-31 15:01:37 +010016136 add_verb(spec, alc861vd_volume_init_verbs);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016137
16138 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020016139 spec->input_mux = &spec->private_imux[0];
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016140
Takashi Iwai776e1842007-08-29 15:07:11 +020016141 err = alc_auto_add_mic_boost(codec);
16142 if (err < 0)
16143 return err;
16144
Kailang Yang6227cdc2010-02-25 08:36:52 +010016145 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020016146
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016147 return 1;
16148}
16149
16150/* additional initialization for auto-configuration model */
16151static void alc861vd_auto_init(struct hda_codec *codec)
16152{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016153 struct alc_spec *spec = codec->spec;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016154 alc861vd_auto_init_multi_out(codec);
16155 alc861vd_auto_init_hp_out(codec);
16156 alc861vd_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020016157 alc861vd_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016158 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020016159 alc_inithook(codec);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016160}
16161
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016162enum {
16163 ALC660VD_FIX_ASUS_GPIO1
16164};
16165
16166/* reset GPIO1 */
16167static const struct hda_verb alc660vd_fix_asus_gpio1_verbs[] = {
16168 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
16169 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
16170 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
16171 { }
16172};
16173
16174static const struct alc_fixup alc861vd_fixups[] = {
16175 [ALC660VD_FIX_ASUS_GPIO1] = {
16176 .verbs = alc660vd_fix_asus_gpio1_verbs,
16177 },
16178};
16179
16180static struct snd_pci_quirk alc861vd_fixup_tbl[] = {
16181 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
16182 {}
16183};
16184
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016185static int patch_alc861vd(struct hda_codec *codec)
16186{
16187 struct alc_spec *spec;
16188 int err, board_config;
16189
16190 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
16191 if (spec == NULL)
16192 return -ENOMEM;
16193
16194 codec->spec = spec;
16195
16196 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
16197 alc861vd_models,
16198 alc861vd_cfg_tbl);
16199
16200 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020016201 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
16202 codec->chip_name);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016203 board_config = ALC861VD_AUTO;
16204 }
16205
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016206 alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups);
16207
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016208 if (board_config == ALC861VD_AUTO) {
16209 /* automatic parse from the BIOS config */
16210 err = alc861vd_parse_auto_config(codec);
16211 if (err < 0) {
16212 alc_free(codec);
16213 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016214 } else if (!err) {
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016215 printk(KERN_INFO
16216 "hda_codec: Cannot set up configuration "
16217 "from BIOS. Using base mode...\n");
16218 board_config = ALC861VD_3ST;
16219 }
16220 }
16221
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090016222 err = snd_hda_attach_beep_device(codec, 0x23);
16223 if (err < 0) {
16224 alc_free(codec);
16225 return err;
16226 }
16227
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016228 if (board_config != ALC861VD_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020016229 setup_preset(codec, &alc861vd_presets[board_config]);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016230
Kailang Yang2f893282008-05-27 12:14:47 +020016231 if (codec->vendor_id == 0x10ec0660) {
Kailang Yangf9423e72008-05-27 12:32:25 +020016232 /* always turn on EAPD */
Takashi Iwaid88897e2008-10-31 15:01:37 +010016233 add_verb(spec, alc660vd_eapd_verbs);
Kailang Yang2f893282008-05-27 12:14:47 +020016234 }
16235
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016236 spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
16237 spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
16238
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016239 spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
16240 spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
16241
Takashi Iwaidd704692009-08-11 08:45:11 +020016242 if (!spec->adc_nids) {
16243 spec->adc_nids = alc861vd_adc_nids;
16244 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
16245 }
16246 if (!spec->capsrc_nids)
16247 spec->capsrc_nids = alc861vd_capsrc_nids;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016248
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016249 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010016250 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016251
Takashi Iwai2134ea42008-01-10 16:53:55 +010016252 spec->vmaster_nid = 0x02;
16253
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016254 codec->patch_ops = alc_patch_ops;
16255
16256 if (board_config == ALC861VD_AUTO)
16257 spec->init_hook = alc861vd_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020016258#ifdef CONFIG_SND_HDA_POWER_SAVE
16259 if (!spec->loopback.amplist)
16260 spec->loopback.amplist = alc861vd_loopbacks;
16261#endif
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016262
16263 return 0;
16264}
16265
16266/*
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016267 * ALC662 support
16268 *
16269 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
16270 * configuration. Each pin widget can choose any input DACs and a mixer.
16271 * Each ADC is connected from a mixer of all inputs. This makes possible
16272 * 6-channel independent captures.
16273 *
16274 * In addition, an independent DAC for the multi-playback (not used in this
16275 * driver yet).
16276 */
16277#define ALC662_DIGOUT_NID 0x06
16278#define ALC662_DIGIN_NID 0x0a
16279
16280static hda_nid_t alc662_dac_nids[4] = {
16281 /* front, rear, clfe, rear_surr */
16282 0x02, 0x03, 0x04
16283};
16284
Kailang Yang622e84c2009-04-21 07:39:04 +020016285static hda_nid_t alc272_dac_nids[2] = {
16286 0x02, 0x03
16287};
16288
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016289static hda_nid_t alc662_adc_nids[2] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016290 /* ADC1-2 */
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016291 0x09, 0x08
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016292};
Takashi Iwaie1406342008-02-11 18:32:32 +010016293
Kailang Yang622e84c2009-04-21 07:39:04 +020016294static hda_nid_t alc272_adc_nids[1] = {
16295 /* ADC1-2 */
16296 0x08,
16297};
16298
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016299static hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
Kailang Yang622e84c2009-04-21 07:39:04 +020016300static hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
16301
Takashi Iwaie1406342008-02-11 18:32:32 +010016302
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016303/* input MUX */
16304/* FIXME: should be a matrix-type input source selection */
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016305static struct hda_input_mux alc662_capture_source = {
16306 .num_items = 4,
16307 .items = {
16308 { "Mic", 0x0 },
16309 { "Front Mic", 0x1 },
16310 { "Line", 0x2 },
16311 { "CD", 0x4 },
16312 },
16313};
16314
16315static struct hda_input_mux alc662_lenovo_101e_capture_source = {
16316 .num_items = 2,
16317 .items = {
16318 { "Mic", 0x1 },
16319 { "Line", 0x2 },
16320 },
16321};
Kailang Yang291702f2007-10-16 14:28:03 +020016322
Kailang Yang6dda9f42008-05-27 12:05:31 +020016323static struct hda_input_mux alc663_capture_source = {
16324 .num_items = 3,
16325 .items = {
16326 { "Mic", 0x0 },
16327 { "Front Mic", 0x1 },
16328 { "Line", 0x2 },
16329 },
16330};
16331
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016332#if 0 /* set to 1 for testing other input sources below */
Chris Pockelé9541ba12009-05-12 08:08:53 +020016333static struct hda_input_mux alc272_nc10_capture_source = {
16334 .num_items = 16,
16335 .items = {
16336 { "Autoselect Mic", 0x0 },
16337 { "Internal Mic", 0x1 },
16338 { "In-0x02", 0x2 },
16339 { "In-0x03", 0x3 },
16340 { "In-0x04", 0x4 },
16341 { "In-0x05", 0x5 },
16342 { "In-0x06", 0x6 },
16343 { "In-0x07", 0x7 },
16344 { "In-0x08", 0x8 },
16345 { "In-0x09", 0x9 },
16346 { "In-0x0a", 0x0a },
16347 { "In-0x0b", 0x0b },
16348 { "In-0x0c", 0x0c },
16349 { "In-0x0d", 0x0d },
16350 { "In-0x0e", 0x0e },
16351 { "In-0x0f", 0x0f },
16352 },
16353};
16354#endif
16355
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016356/*
16357 * 2ch mode
16358 */
16359static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
16360 { 2, NULL }
16361};
16362
16363/*
16364 * 2ch mode
16365 */
16366static struct hda_verb alc662_3ST_ch2_init[] = {
16367 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
16368 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
16369 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
16370 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
16371 { } /* end */
16372};
16373
16374/*
16375 * 6ch mode
16376 */
16377static struct hda_verb alc662_3ST_ch6_init[] = {
16378 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16379 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
16380 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
16381 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16382 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
16383 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
16384 { } /* end */
16385};
16386
16387static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
16388 { 2, alc662_3ST_ch2_init },
16389 { 6, alc662_3ST_ch6_init },
16390};
16391
16392/*
16393 * 2ch mode
16394 */
16395static struct hda_verb alc662_sixstack_ch6_init[] = {
16396 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
16397 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
16398 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16399 { } /* end */
16400};
16401
16402/*
16403 * 6ch mode
16404 */
16405static struct hda_verb alc662_sixstack_ch8_init[] = {
16406 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16407 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16408 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
16409 { } /* end */
16410};
16411
16412static struct hda_channel_mode alc662_5stack_modes[2] = {
16413 { 2, alc662_sixstack_ch6_init },
16414 { 6, alc662_sixstack_ch8_init },
16415};
16416
16417/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
16418 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
16419 */
16420
16421static struct snd_kcontrol_new alc662_base_mixer[] = {
16422 /* output mixer control */
16423 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016424 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016425 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016426 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016427 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
16428 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016429 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
16430 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016431 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16432
16433 /*Input mixer control */
16434 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
16435 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
16436 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
16437 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
16438 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
16439 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
16440 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
16441 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016442 { } /* end */
16443};
16444
16445static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
16446 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016447 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016448 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16449 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16450 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16451 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16452 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16453 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16454 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16455 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16456 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016457 { } /* end */
16458};
16459
16460static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
16461 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016462 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016463 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016464 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016465 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
16466 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010016467 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
16468 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016469 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16470 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16471 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16472 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16473 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16474 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16475 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16476 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16477 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016478 { } /* end */
16479};
16480
16481static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
16482 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16483 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +010016484 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16485 HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016486 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16487 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16488 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16489 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16490 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016491 { } /* end */
16492};
16493
Kailang Yang291702f2007-10-16 14:28:03 +020016494static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020016495 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16496 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang291702f2007-10-16 14:28:03 +020016497
16498 HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT),
16499 HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16500 HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16501
16502 HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),
16503 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16504 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16505 { } /* end */
16506};
16507
Kailang Yang8c427222008-01-10 13:03:59 +010016508static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020016509 ALC262_HIPPO_MASTER_SWITCH,
16510 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010016511 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010016512 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
16513 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010016514 HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
16515 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16516 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16517 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16518 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16519 { } /* end */
16520};
16521
Kailang Yangf1d4e282008-08-26 14:03:29 +020016522static struct hda_bind_ctls alc663_asus_bind_master_vol = {
16523 .ops = &snd_hda_bind_vol,
16524 .values = {
16525 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
16526 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
16527 0
16528 },
16529};
16530
16531static struct hda_bind_ctls alc663_asus_one_bind_switch = {
16532 .ops = &snd_hda_bind_sw,
16533 .values = {
16534 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16535 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
16536 0
16537 },
16538};
16539
Kailang Yang6dda9f42008-05-27 12:05:31 +020016540static struct snd_kcontrol_new alc663_m51va_mixer[] = {
Kailang Yangf1d4e282008-08-26 14:03:29 +020016541 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
16542 HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
16543 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16544 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16545 { } /* end */
16546};
16547
16548static struct hda_bind_ctls alc663_asus_tree_bind_switch = {
16549 .ops = &snd_hda_bind_sw,
16550 .values = {
16551 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16552 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
16553 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
16554 0
16555 },
16556};
16557
16558static struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
16559 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
16560 HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
16561 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16562 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16563 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16564 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16565
16566 { } /* end */
16567};
16568
16569static struct hda_bind_ctls alc663_asus_four_bind_switch = {
16570 .ops = &snd_hda_bind_sw,
16571 .values = {
16572 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16573 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
16574 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
16575 0
16576 },
16577};
16578
16579static struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
16580 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
16581 HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
16582 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16583 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16584 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16585 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16586 { } /* end */
16587};
16588
16589static struct snd_kcontrol_new alc662_1bjd_mixer[] = {
Kailang Yang6dda9f42008-05-27 12:05:31 +020016590 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16591 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Kailang Yangf1d4e282008-08-26 14:03:29 +020016592 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16593 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16594 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16595 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16596 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16597 { } /* end */
16598};
16599
16600static struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
16601 .ops = &snd_hda_bind_vol,
16602 .values = {
16603 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
16604 HDA_COMPOSE_AMP_VAL(0x04, 3, 0, HDA_OUTPUT),
16605 0
16606 },
16607};
16608
16609static struct hda_bind_ctls alc663_asus_two_bind_switch = {
16610 .ops = &snd_hda_bind_sw,
16611 .values = {
16612 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16613 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT),
16614 0
16615 },
16616};
16617
16618static struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
16619 HDA_BIND_VOL("Master Playback Volume",
16620 &alc663_asus_two_bind_master_vol),
16621 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
16622 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yang6dda9f42008-05-27 12:05:31 +020016623 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16624 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16625 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangf1d4e282008-08-26 14:03:29 +020016626 { } /* end */
16627};
16628
16629static struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
16630 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
16631 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
16632 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16633 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
16634 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16635 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yang6dda9f42008-05-27 12:05:31 +020016636 { } /* end */
16637};
16638
16639static struct snd_kcontrol_new alc663_g71v_mixer[] = {
16640 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16641 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
16642 HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16643 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
16644 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16645
16646 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16647 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16648 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16649 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16650 { } /* end */
16651};
16652
16653static struct snd_kcontrol_new alc663_g50v_mixer[] = {
16654 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16655 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
16656 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16657
16658 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16659 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16660 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16661 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16662 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16663 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16664 { } /* end */
16665};
16666
Kailang Yangebb83ee2009-12-17 12:23:00 +010016667static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
16668 .ops = &snd_hda_bind_sw,
16669 .values = {
16670 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16671 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
16672 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
16673 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
16674 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
16675 0
16676 },
16677};
16678
16679static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
16680 .ops = &snd_hda_bind_sw,
16681 .values = {
16682 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
16683 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
16684 0
16685 },
16686};
16687
16688static struct snd_kcontrol_new alc663_mode7_mixer[] = {
16689 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
16690 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
16691 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
16692 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16693 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16694 HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16695 HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16696 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16697 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16698 { } /* end */
16699};
16700
16701static struct snd_kcontrol_new alc663_mode8_mixer[] = {
16702 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
16703 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
16704 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
16705 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
16706 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
16707 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16708 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16709 { } /* end */
16710};
16711
16712
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016713static struct snd_kcontrol_new alc662_chmode_mixer[] = {
16714 {
16715 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16716 .name = "Channel Mode",
16717 .info = alc_ch_mode_info,
16718 .get = alc_ch_mode_get,
16719 .put = alc_ch_mode_put,
16720 },
16721 { } /* end */
16722};
16723
16724static struct hda_verb alc662_init_verbs[] = {
16725 /* ADC: mute amp left and right */
16726 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16727 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016728
Kailang Yangb60dd392007-09-20 12:50:29 +020016729 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16730 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16731 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16732 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16733 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16734 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016735
16736 /* Front Pin: output 0 (0x0c) */
16737 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16738 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16739
16740 /* Rear Pin: output 1 (0x0d) */
16741 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16742 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16743
16744 /* CLFE Pin: output 2 (0x0e) */
16745 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16746 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16747
16748 /* Mic (rear) pin: input vref at 80% */
16749 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16750 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16751 /* Front Mic pin: input vref at 80% */
16752 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16753 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16754 /* Line In pin: input */
16755 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16756 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16757 /* Line-2 In: Headphone output (output 0 - 0x0c) */
16758 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16759 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16760 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
16761 /* CD pin widget for input */
16762 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16763
16764 /* FIXME: use matrix-type input source selection */
16765 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
16766 /* Input mixer */
16767 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yang291702f2007-10-16 14:28:03 +020016768 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yang6dda9f42008-05-27 12:05:31 +020016769
16770 /* always trun on EAPD */
16771 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
16772 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
16773
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016774 { }
16775};
16776
Kailang Yangcec27c82010-02-04 14:18:18 +010016777static struct hda_verb alc663_init_verbs[] = {
16778 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16779 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16780 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16781 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16782 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16783 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16784 { }
16785};
16786
16787static struct hda_verb alc272_init_verbs[] = {
16788 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16789 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16790 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16791 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16792 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16793 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16794 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16795 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16796 { }
16797};
16798
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016799static struct hda_verb alc662_sue_init_verbs[] = {
16800 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
16801 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
Kailang Yang291702f2007-10-16 14:28:03 +020016802 {}
16803};
16804
16805static struct hda_verb alc662_eeepc_sue_init_verbs[] = {
16806 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16807 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16808 {}
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016809};
16810
Kailang Yang8c427222008-01-10 13:03:59 +010016811/* Set Unsolicited Event*/
16812static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
16813 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16814 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16815 {}
16816};
16817
Kailang Yang6dda9f42008-05-27 12:05:31 +020016818static struct hda_verb alc663_m51va_init_verbs[] = {
Kailang Yangf1d4e282008-08-26 14:03:29 +020016819 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16820 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yang6dda9f42008-05-27 12:05:31 +020016821 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16822 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangf1d4e282008-08-26 14:03:29 +020016823 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16824 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16825 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
Kailang Yang6dda9f42008-05-27 12:05:31 +020016826 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16827 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16828 {}
16829};
16830
Kailang Yangf1d4e282008-08-26 14:03:29 +020016831static struct hda_verb alc663_21jd_amic_init_verbs[] = {
16832 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16833 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16834 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16835 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16836 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16837 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16838 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16839 {}
16840};
16841
16842static struct hda_verb alc662_1bjd_amic_init_verbs[] = {
16843 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16844 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16845 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16846 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
16847 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16848 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16849 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16850 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16851 {}
16852};
16853
16854static struct hda_verb alc663_15jd_amic_init_verbs[] = {
16855 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16856 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16857 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16858 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16859 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16860 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16861 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16862 {}
16863};
16864
16865static struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
16866 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16867 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16868 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16869 {0x21, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
16870 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16871 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16872 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
16873 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16874 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16875 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16876 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16877 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16878 {}
16879};
16880
16881static struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
16882 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16883 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16884 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16885 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16886 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16887 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16888 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16889 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16890 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16891 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16892 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16893 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16894 {}
16895};
16896
Kailang Yang6dda9f42008-05-27 12:05:31 +020016897static struct hda_verb alc663_g71v_init_verbs[] = {
16898 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16899 /* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
16900 /* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
16901
16902 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16903 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16904 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
16905
16906 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
16907 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
16908 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
16909 {}
16910};
16911
16912static struct hda_verb alc663_g50v_init_verbs[] = {
16913 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16914 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16915 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
16916
16917 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16918 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16919 {}
16920};
16921
Kailang Yangf1d4e282008-08-26 14:03:29 +020016922static struct hda_verb alc662_ecs_init_verbs[] = {
16923 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
16924 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16925 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16926 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16927 {}
16928};
16929
Kailang Yang622e84c2009-04-21 07:39:04 +020016930static struct hda_verb alc272_dell_zm1_init_verbs[] = {
16931 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16932 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16933 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16934 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16935 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16936 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16937 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16938 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16939 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
16940 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16941 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16942 {}
16943};
16944
16945static struct hda_verb alc272_dell_init_verbs[] = {
16946 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16947 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16948 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16949 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16950 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16951 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16952 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16953 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16954 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
16955 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16956 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16957 {}
16958};
16959
Kailang Yangebb83ee2009-12-17 12:23:00 +010016960static struct hda_verb alc663_mode7_init_verbs[] = {
16961 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16962 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16963 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16964 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16965 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16966 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16967 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
16968 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16969 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16970 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16971 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16972 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
16973 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16974 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16975 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16976 {}
16977};
16978
16979static struct hda_verb alc663_mode8_init_verbs[] = {
16980 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16981 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16982 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16983 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
16984 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16985 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16986 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16987 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16988 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16989 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16990 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
16991 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16992 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
16993 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16994 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
16995 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16996 {}
16997};
16998
Kailang Yangf1d4e282008-08-26 14:03:29 +020016999static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
17000 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
17001 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
17002 { } /* end */
17003};
17004
Kailang Yang622e84c2009-04-21 07:39:04 +020017005static struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
17006 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
17007 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
17008 { } /* end */
17009};
17010
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017011static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
17012{
17013 unsigned int present;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017014 unsigned char bits;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017015
Wu Fengguang864f92b2009-11-18 12:38:02 +080017016 present = snd_hda_jack_detect(codec, 0x14);
Takashi Iwai47fd8302007-08-10 17:11:07 +020017017 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080017018
Takashi Iwai47fd8302007-08-10 17:11:07 +020017019 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
17020 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017021}
17022
17023static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
17024{
17025 unsigned int present;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017026 unsigned char bits;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017027
Wu Fengguang864f92b2009-11-18 12:38:02 +080017028 present = snd_hda_jack_detect(codec, 0x1b);
Takashi Iwai47fd8302007-08-10 17:11:07 +020017029 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080017030
Takashi Iwai47fd8302007-08-10 17:11:07 +020017031 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
17032 HDA_AMP_MUTE, bits);
17033 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
17034 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017035}
17036
17037static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
17038 unsigned int res)
17039{
17040 if ((res >> 26) == ALC880_HP_EVENT)
17041 alc662_lenovo_101e_all_automute(codec);
17042 if ((res >> 26) == ALC880_FRONT_EVENT)
17043 alc662_lenovo_101e_ispeaker_automute(codec);
17044}
17045
Kailang Yang291702f2007-10-16 14:28:03 +020017046/* unsolicited event for HP jack sensing */
17047static void alc662_eeepc_unsol_event(struct hda_codec *codec,
17048 unsigned int res)
17049{
Kailang Yang291702f2007-10-16 14:28:03 +020017050 if ((res >> 26) == ALC880_MIC_EVENT)
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017051 alc_mic_automute(codec);
Takashi Iwai42171c12009-05-08 14:11:43 +020017052 else
17053 alc262_hippo_unsol_event(codec, res);
Kailang Yang291702f2007-10-16 14:28:03 +020017054}
17055
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017056static void alc662_eeepc_setup(struct hda_codec *codec)
Kailang Yang291702f2007-10-16 14:28:03 +020017057{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017058 struct alc_spec *spec = codec->spec;
17059
17060 alc262_hippo1_setup(codec);
17061 spec->ext_mic.pin = 0x18;
17062 spec->ext_mic.mux_idx = 0;
17063 spec->int_mic.pin = 0x19;
17064 spec->int_mic.mux_idx = 1;
17065 spec->auto_mic = 1;
Kailang Yang291702f2007-10-16 14:28:03 +020017066}
17067
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017068static void alc662_eeepc_inithook(struct hda_codec *codec)
17069{
17070 alc262_hippo_automute(codec);
17071 alc_mic_automute(codec);
17072}
17073
17074static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
Kailang Yang8c427222008-01-10 13:03:59 +010017075{
Takashi Iwai42171c12009-05-08 14:11:43 +020017076 struct alc_spec *spec = codec->spec;
17077
17078 spec->autocfg.hp_pins[0] = 0x14;
17079 spec->autocfg.speaker_pins[0] = 0x1b;
Kailang Yang8c427222008-01-10 13:03:59 +010017080}
17081
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017082#define alc662_eeepc_ep20_inithook alc262_hippo_master_update
17083
Kailang Yang6dda9f42008-05-27 12:05:31 +020017084static void alc663_m51va_speaker_automute(struct hda_codec *codec)
17085{
17086 unsigned int present;
17087 unsigned char bits;
17088
Wu Fengguang864f92b2009-11-18 12:38:02 +080017089 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017090 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yangf1d4e282008-08-26 14:03:29 +020017091 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
17092 AMP_IN_MUTE(0), bits);
17093 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
17094 AMP_IN_MUTE(0), bits);
17095}
17096
17097static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
17098{
17099 unsigned int present;
17100 unsigned char bits;
17101
Wu Fengguang864f92b2009-11-18 12:38:02 +080017102 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017103 bits = present ? HDA_AMP_MUTE : 0;
17104 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
17105 AMP_IN_MUTE(0), bits);
17106 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
17107 AMP_IN_MUTE(0), bits);
17108 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
17109 AMP_IN_MUTE(0), bits);
17110 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
17111 AMP_IN_MUTE(0), bits);
17112}
17113
17114static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
17115{
17116 unsigned int present;
17117 unsigned char bits;
17118
Wu Fengguang864f92b2009-11-18 12:38:02 +080017119 present = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017120 bits = present ? HDA_AMP_MUTE : 0;
17121 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
17122 AMP_IN_MUTE(0), bits);
17123 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
17124 AMP_IN_MUTE(0), bits);
17125 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
17126 AMP_IN_MUTE(0), bits);
17127 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
17128 AMP_IN_MUTE(0), bits);
17129}
17130
17131static void alc662_f5z_speaker_automute(struct hda_codec *codec)
17132{
17133 unsigned int present;
17134 unsigned char bits;
17135
Wu Fengguang864f92b2009-11-18 12:38:02 +080017136 present = snd_hda_jack_detect(codec, 0x1b);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017137 bits = present ? 0 : PIN_OUT;
17138 snd_hda_codec_write(codec, 0x14, 0,
17139 AC_VERB_SET_PIN_WIDGET_CONTROL, bits);
17140}
17141
17142static void alc663_two_hp_m1_speaker_automute(struct hda_codec *codec)
17143{
17144 unsigned int present1, present2;
17145
Wu Fengguang864f92b2009-11-18 12:38:02 +080017146 present1 = snd_hda_jack_detect(codec, 0x21);
17147 present2 = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017148
17149 if (present1 || present2) {
17150 snd_hda_codec_write_cache(codec, 0x14, 0,
17151 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17152 } else {
17153 snd_hda_codec_write_cache(codec, 0x14, 0,
17154 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17155 }
17156}
17157
17158static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
17159{
17160 unsigned int present1, present2;
17161
Wu Fengguang864f92b2009-11-18 12:38:02 +080017162 present1 = snd_hda_jack_detect(codec, 0x1b);
17163 present2 = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017164
17165 if (present1 || present2) {
17166 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
17167 AMP_IN_MUTE(0), AMP_IN_MUTE(0));
17168 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
17169 AMP_IN_MUTE(0), AMP_IN_MUTE(0));
17170 } else {
17171 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
17172 AMP_IN_MUTE(0), 0);
17173 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
17174 AMP_IN_MUTE(0), 0);
17175 }
Kailang Yang6dda9f42008-05-27 12:05:31 +020017176}
17177
Kailang Yangebb83ee2009-12-17 12:23:00 +010017178static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec)
17179{
17180 unsigned int present1, present2;
17181
17182 present1 = snd_hda_codec_read(codec, 0x1b, 0,
17183 AC_VERB_GET_PIN_SENSE, 0)
17184 & AC_PINSENSE_PRESENCE;
17185 present2 = snd_hda_codec_read(codec, 0x21, 0,
17186 AC_VERB_GET_PIN_SENSE, 0)
17187 & AC_PINSENSE_PRESENCE;
17188
17189 if (present1 || present2) {
17190 snd_hda_codec_write_cache(codec, 0x14, 0,
17191 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17192 snd_hda_codec_write_cache(codec, 0x17, 0,
17193 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17194 } else {
17195 snd_hda_codec_write_cache(codec, 0x14, 0,
17196 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17197 snd_hda_codec_write_cache(codec, 0x17, 0,
17198 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17199 }
17200}
17201
17202static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec)
17203{
17204 unsigned int present1, present2;
17205
17206 present1 = snd_hda_codec_read(codec, 0x21, 0,
17207 AC_VERB_GET_PIN_SENSE, 0)
17208 & AC_PINSENSE_PRESENCE;
17209 present2 = snd_hda_codec_read(codec, 0x15, 0,
17210 AC_VERB_GET_PIN_SENSE, 0)
17211 & AC_PINSENSE_PRESENCE;
17212
17213 if (present1 || present2) {
17214 snd_hda_codec_write_cache(codec, 0x14, 0,
17215 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17216 snd_hda_codec_write_cache(codec, 0x17, 0,
17217 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17218 } else {
17219 snd_hda_codec_write_cache(codec, 0x14, 0,
17220 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17221 snd_hda_codec_write_cache(codec, 0x17, 0,
17222 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17223 }
17224}
17225
Kailang Yang6dda9f42008-05-27 12:05:31 +020017226static void alc663_m51va_unsol_event(struct hda_codec *codec,
17227 unsigned int res)
17228{
17229 switch (res >> 26) {
17230 case ALC880_HP_EVENT:
17231 alc663_m51va_speaker_automute(codec);
17232 break;
17233 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017234 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017235 break;
17236 }
17237}
17238
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017239static void alc663_m51va_setup(struct hda_codec *codec)
17240{
17241 struct alc_spec *spec = codec->spec;
17242 spec->ext_mic.pin = 0x18;
17243 spec->ext_mic.mux_idx = 0;
17244 spec->int_mic.pin = 0x12;
Kailang Yangebb83ee2009-12-17 12:23:00 +010017245 spec->int_mic.mux_idx = 9;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017246 spec->auto_mic = 1;
17247}
17248
Kailang Yang6dda9f42008-05-27 12:05:31 +020017249static void alc663_m51va_inithook(struct hda_codec *codec)
17250{
17251 alc663_m51va_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017252 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017253}
17254
Kailang Yangf1d4e282008-08-26 14:03:29 +020017255/* ***************** Mode1 ******************************/
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017256#define alc663_mode1_unsol_event alc663_m51va_unsol_event
Kailang Yangebb83ee2009-12-17 12:23:00 +010017257
17258static void alc663_mode1_setup(struct hda_codec *codec)
17259{
17260 struct alc_spec *spec = codec->spec;
17261 spec->ext_mic.pin = 0x18;
17262 spec->ext_mic.mux_idx = 0;
17263 spec->int_mic.pin = 0x19;
17264 spec->int_mic.mux_idx = 1;
17265 spec->auto_mic = 1;
17266}
17267
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017268#define alc663_mode1_inithook alc663_m51va_inithook
Kailang Yangf1d4e282008-08-26 14:03:29 +020017269
Kailang Yangf1d4e282008-08-26 14:03:29 +020017270/* ***************** Mode2 ******************************/
17271static void alc662_mode2_unsol_event(struct hda_codec *codec,
17272 unsigned int res)
17273{
17274 switch (res >> 26) {
17275 case ALC880_HP_EVENT:
17276 alc662_f5z_speaker_automute(codec);
17277 break;
17278 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017279 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017280 break;
17281 }
17282}
17283
Kailang Yangebb83ee2009-12-17 12:23:00 +010017284#define alc662_mode2_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017285
Kailang Yangf1d4e282008-08-26 14:03:29 +020017286static void alc662_mode2_inithook(struct hda_codec *codec)
17287{
17288 alc662_f5z_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017289 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017290}
17291/* ***************** Mode3 ******************************/
17292static void alc663_mode3_unsol_event(struct hda_codec *codec,
17293 unsigned int res)
17294{
17295 switch (res >> 26) {
17296 case ALC880_HP_EVENT:
17297 alc663_two_hp_m1_speaker_automute(codec);
17298 break;
17299 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017300 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017301 break;
17302 }
17303}
17304
Kailang Yangebb83ee2009-12-17 12:23:00 +010017305#define alc663_mode3_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017306
Kailang Yangf1d4e282008-08-26 14:03:29 +020017307static void alc663_mode3_inithook(struct hda_codec *codec)
17308{
17309 alc663_two_hp_m1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017310 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017311}
17312/* ***************** Mode4 ******************************/
17313static void alc663_mode4_unsol_event(struct hda_codec *codec,
17314 unsigned int res)
17315{
17316 switch (res >> 26) {
17317 case ALC880_HP_EVENT:
17318 alc663_21jd_two_speaker_automute(codec);
17319 break;
17320 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017321 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017322 break;
17323 }
17324}
17325
Kailang Yangebb83ee2009-12-17 12:23:00 +010017326#define alc663_mode4_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017327
Kailang Yangf1d4e282008-08-26 14:03:29 +020017328static void alc663_mode4_inithook(struct hda_codec *codec)
17329{
17330 alc663_21jd_two_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017331 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017332}
17333/* ***************** Mode5 ******************************/
17334static void alc663_mode5_unsol_event(struct hda_codec *codec,
17335 unsigned int res)
17336{
17337 switch (res >> 26) {
17338 case ALC880_HP_EVENT:
17339 alc663_15jd_two_speaker_automute(codec);
17340 break;
17341 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017342 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017343 break;
17344 }
17345}
17346
Kailang Yangebb83ee2009-12-17 12:23:00 +010017347#define alc663_mode5_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017348
Kailang Yangf1d4e282008-08-26 14:03:29 +020017349static void alc663_mode5_inithook(struct hda_codec *codec)
17350{
17351 alc663_15jd_two_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017352 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017353}
17354/* ***************** Mode6 ******************************/
17355static void alc663_mode6_unsol_event(struct hda_codec *codec,
17356 unsigned int res)
17357{
17358 switch (res >> 26) {
17359 case ALC880_HP_EVENT:
17360 alc663_two_hp_m2_speaker_automute(codec);
17361 break;
17362 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017363 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017364 break;
17365 }
17366}
17367
Kailang Yangebb83ee2009-12-17 12:23:00 +010017368#define alc663_mode6_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017369
Kailang Yangf1d4e282008-08-26 14:03:29 +020017370static void alc663_mode6_inithook(struct hda_codec *codec)
17371{
17372 alc663_two_hp_m2_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017373 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017374}
17375
Kailang Yangebb83ee2009-12-17 12:23:00 +010017376/* ***************** Mode7 ******************************/
17377static void alc663_mode7_unsol_event(struct hda_codec *codec,
17378 unsigned int res)
17379{
17380 switch (res >> 26) {
17381 case ALC880_HP_EVENT:
17382 alc663_two_hp_m7_speaker_automute(codec);
17383 break;
17384 case ALC880_MIC_EVENT:
17385 alc_mic_automute(codec);
17386 break;
17387 }
17388}
17389
17390#define alc663_mode7_setup alc663_mode1_setup
17391
17392static void alc663_mode7_inithook(struct hda_codec *codec)
17393{
17394 alc663_two_hp_m7_speaker_automute(codec);
17395 alc_mic_automute(codec);
17396}
17397
17398/* ***************** Mode8 ******************************/
17399static void alc663_mode8_unsol_event(struct hda_codec *codec,
17400 unsigned int res)
17401{
17402 switch (res >> 26) {
17403 case ALC880_HP_EVENT:
17404 alc663_two_hp_m8_speaker_automute(codec);
17405 break;
17406 case ALC880_MIC_EVENT:
17407 alc_mic_automute(codec);
17408 break;
17409 }
17410}
17411
17412#define alc663_mode8_setup alc663_m51va_setup
17413
17414static void alc663_mode8_inithook(struct hda_codec *codec)
17415{
17416 alc663_two_hp_m8_speaker_automute(codec);
17417 alc_mic_automute(codec);
17418}
17419
Kailang Yang6dda9f42008-05-27 12:05:31 +020017420static void alc663_g71v_hp_automute(struct hda_codec *codec)
17421{
17422 unsigned int present;
17423 unsigned char bits;
17424
Wu Fengguang864f92b2009-11-18 12:38:02 +080017425 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017426 bits = present ? HDA_AMP_MUTE : 0;
17427 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
17428 HDA_AMP_MUTE, bits);
17429 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
17430 HDA_AMP_MUTE, bits);
17431}
17432
17433static void alc663_g71v_front_automute(struct hda_codec *codec)
17434{
17435 unsigned int present;
17436 unsigned char bits;
17437
Wu Fengguang864f92b2009-11-18 12:38:02 +080017438 present = snd_hda_jack_detect(codec, 0x15);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017439 bits = present ? HDA_AMP_MUTE : 0;
17440 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
17441 HDA_AMP_MUTE, bits);
17442}
17443
17444static void alc663_g71v_unsol_event(struct hda_codec *codec,
17445 unsigned int res)
17446{
17447 switch (res >> 26) {
17448 case ALC880_HP_EVENT:
17449 alc663_g71v_hp_automute(codec);
17450 break;
17451 case ALC880_FRONT_EVENT:
17452 alc663_g71v_front_automute(codec);
17453 break;
17454 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017455 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017456 break;
17457 }
17458}
17459
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017460#define alc663_g71v_setup alc663_m51va_setup
17461
Kailang Yang6dda9f42008-05-27 12:05:31 +020017462static void alc663_g71v_inithook(struct hda_codec *codec)
17463{
17464 alc663_g71v_front_automute(codec);
17465 alc663_g71v_hp_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017466 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017467}
17468
17469static void alc663_g50v_unsol_event(struct hda_codec *codec,
17470 unsigned int res)
17471{
17472 switch (res >> 26) {
17473 case ALC880_HP_EVENT:
17474 alc663_m51va_speaker_automute(codec);
17475 break;
17476 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017477 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017478 break;
17479 }
17480}
17481
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017482#define alc663_g50v_setup alc663_m51va_setup
17483
Kailang Yang6dda9f42008-05-27 12:05:31 +020017484static void alc663_g50v_inithook(struct hda_codec *codec)
17485{
17486 alc663_m51va_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017487 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017488}
17489
Kailang Yangf1d4e282008-08-26 14:03:29 +020017490static struct snd_kcontrol_new alc662_ecs_mixer[] = {
17491 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Takashi Iwai42171c12009-05-08 14:11:43 +020017492 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017493
17494 HDA_CODEC_VOLUME("e-Mic/LineIn Boost", 0x18, 0, HDA_INPUT),
17495 HDA_CODEC_VOLUME("e-Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
17496 HDA_CODEC_MUTE("e-Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT),
17497
17498 HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),
17499 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17500 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17501 { } /* end */
17502};
17503
Chris Pockelé9541ba12009-05-12 08:08:53 +020017504static struct snd_kcontrol_new alc272_nc10_mixer[] = {
17505 /* Master Playback automatically created from Speaker and Headphone */
17506 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17507 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17508 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17509 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17510
17511 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17512 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17513 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
17514
17515 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17516 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17517 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
17518 { } /* end */
17519};
17520
Takashi Iwaicb53c622007-08-10 17:21:45 +020017521#ifdef CONFIG_SND_HDA_POWER_SAVE
17522#define alc662_loopbacks alc880_loopbacks
17523#endif
17524
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017525
Sasha Alexandrdef319f2009-06-16 16:00:15 -040017526/* pcm configuration: identical with ALC880 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017527#define alc662_pcm_analog_playback alc880_pcm_analog_playback
17528#define alc662_pcm_analog_capture alc880_pcm_analog_capture
17529#define alc662_pcm_digital_playback alc880_pcm_digital_playback
17530#define alc662_pcm_digital_capture alc880_pcm_digital_capture
17531
17532/*
17533 * configuration and preset
17534 */
17535static const char *alc662_models[ALC662_MODEL_LAST] = {
17536 [ALC662_3ST_2ch_DIG] = "3stack-dig",
17537 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
17538 [ALC662_3ST_6ch] = "3stack-6ch",
17539 [ALC662_5ST_DIG] = "6stack-dig",
17540 [ALC662_LENOVO_101E] = "lenovo-101e",
Takashi Iwaib995d762007-10-17 10:41:06 +020017541 [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
Kailang Yang8c427222008-01-10 13:03:59 +010017542 [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
Kailang Yangf1d4e282008-08-26 14:03:29 +020017543 [ALC662_ECS] = "ecs",
Kailang Yang6dda9f42008-05-27 12:05:31 +020017544 [ALC663_ASUS_M51VA] = "m51va",
17545 [ALC663_ASUS_G71V] = "g71v",
17546 [ALC663_ASUS_H13] = "h13",
17547 [ALC663_ASUS_G50V] = "g50v",
Kailang Yangf1d4e282008-08-26 14:03:29 +020017548 [ALC663_ASUS_MODE1] = "asus-mode1",
17549 [ALC662_ASUS_MODE2] = "asus-mode2",
17550 [ALC663_ASUS_MODE3] = "asus-mode3",
17551 [ALC663_ASUS_MODE4] = "asus-mode4",
17552 [ALC663_ASUS_MODE5] = "asus-mode5",
17553 [ALC663_ASUS_MODE6] = "asus-mode6",
Kailang Yangebb83ee2009-12-17 12:23:00 +010017554 [ALC663_ASUS_MODE7] = "asus-mode7",
17555 [ALC663_ASUS_MODE8] = "asus-mode8",
Takashi Iwai01f2bd42009-05-11 08:12:43 +020017556 [ALC272_DELL] = "dell",
17557 [ALC272_DELL_ZM1] = "dell-zm1",
Chris Pockelé9541ba12009-05-12 08:08:53 +020017558 [ALC272_SAMSUNG_NC10] = "samsung-nc10",
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017559 [ALC662_AUTO] = "auto",
17560};
17561
17562static struct snd_pci_quirk alc662_cfg_tbl[] = {
Takashi Iwaidea0a502009-02-09 17:14:52 +010017563 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
Kailang Yang622e84c2009-04-21 07:39:04 +020017564 SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
17565 SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017566 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
17567 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
Kailang Yangcec27c82010-02-04 14:18:18 +010017568 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017569 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
17570 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
17571 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
17572 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
Kailang Yangebb83ee2009-12-17 12:23:00 +010017573 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
17574 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017575 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010017576 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
17577 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
17578 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
17579 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
17580 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017581 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010017582 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
17583 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017584 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
17585 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
17586 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
17587 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010017588 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
Kailang Yang622e84c2009-04-21 07:39:04 +020017589 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
17590 SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
17591 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017592 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
17593 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
17594 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
17595 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020017596 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017597 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
17598 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yang6dda9f42008-05-27 12:05:31 +020017599 SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017600 /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
17601 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
17602 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
Kailang Yang622e84c2009-04-21 07:39:04 +020017603 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
Kailang Yangcec27c82010-02-04 14:18:18 +010017604 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
Kailang Yang622e84c2009-04-21 07:39:04 +020017605 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
17606 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017607 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
17608 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
17609 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020017610 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017611 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
17612 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
Kailang Yang622e84c2009-04-21 07:39:04 +020017613 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017614 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
Kailang Yang80ffe862008-10-15 11:23:27 +020017615 SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017616 /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
17617 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
17618 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020017619 SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017620 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
17621 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
Herton Ronaldo Krzesinski3da23ca2008-03-14 12:52:59 +010017622 SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
Kailang Yang291702f2007-10-16 14:28:03 +020017623 SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
Kailang Yang8c427222008-01-10 13:03:59 +010017624 SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017625 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
Herton Ronaldo Krzesinski95fe5f22008-09-26 23:48:45 -030017626 SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
17627 ALC662_3ST_6ch_DIG),
Takashi Iwai4dee8ba2010-01-13 17:20:08 +010017628 SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
Chris Pockelé9541ba12009-05-12 08:08:53 +020017629 SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
Herton Ronaldo Krzesinskicb559742008-09-26 23:47:45 -030017630 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
17631 ALC662_3ST_6ch_DIG),
Kailang Yang6227cdc2010-02-25 08:36:52 +010017632 SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
Vedran Miletic19c009a2008-09-29 20:29:25 +020017633 SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
Takashi Iwai5bd37292009-04-21 18:36:30 +020017634 SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017635 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
Takashi Iwai238713d2008-10-05 10:57:39 +020017636 SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
Vedran Miletic19c009a2008-09-29 20:29:25 +020017637 ALC662_3ST_6ch_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +010017638 SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
17639 ALC663_ASUS_H13),
David Santinoli7aee6742009-12-09 12:34:26 +010017640 SND_PCI_QUIRK(0x8086, 0xd604, "Intel mobo", ALC662_3ST_2ch_DIG),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017641 {}
17642};
17643
17644static struct alc_config_preset alc662_presets[] = {
17645 [ALC662_3ST_2ch_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017646 .mixers = { alc662_3ST_2ch_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017647 .init_verbs = { alc662_init_verbs },
17648 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17649 .dac_nids = alc662_dac_nids,
17650 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017651 .dig_in_nid = ALC662_DIGIN_NID,
17652 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17653 .channel_mode = alc662_3ST_2ch_modes,
17654 .input_mux = &alc662_capture_source,
17655 },
17656 [ALC662_3ST_6ch_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017657 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017658 .init_verbs = { alc662_init_verbs },
17659 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17660 .dac_nids = alc662_dac_nids,
17661 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017662 .dig_in_nid = ALC662_DIGIN_NID,
17663 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
17664 .channel_mode = alc662_3ST_6ch_modes,
17665 .need_dac_fix = 1,
17666 .input_mux = &alc662_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017667 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017668 [ALC662_3ST_6ch] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017669 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017670 .init_verbs = { alc662_init_verbs },
17671 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17672 .dac_nids = alc662_dac_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017673 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
17674 .channel_mode = alc662_3ST_6ch_modes,
17675 .need_dac_fix = 1,
17676 .input_mux = &alc662_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017677 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017678 [ALC662_5ST_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017679 .mixers = { alc662_base_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017680 .init_verbs = { alc662_init_verbs },
17681 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17682 .dac_nids = alc662_dac_nids,
17683 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017684 .dig_in_nid = ALC662_DIGIN_NID,
17685 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
17686 .channel_mode = alc662_5stack_modes,
17687 .input_mux = &alc662_capture_source,
17688 },
17689 [ALC662_LENOVO_101E] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017690 .mixers = { alc662_lenovo_101e_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017691 .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
17692 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17693 .dac_nids = alc662_dac_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017694 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17695 .channel_mode = alc662_3ST_2ch_modes,
17696 .input_mux = &alc662_lenovo_101e_capture_source,
17697 .unsol_event = alc662_lenovo_101e_unsol_event,
17698 .init_hook = alc662_lenovo_101e_all_automute,
17699 },
Kailang Yang291702f2007-10-16 14:28:03 +020017700 [ALC662_ASUS_EEEPC_P701] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017701 .mixers = { alc662_eeepc_p701_mixer },
Kailang Yang291702f2007-10-16 14:28:03 +020017702 .init_verbs = { alc662_init_verbs,
17703 alc662_eeepc_sue_init_verbs },
17704 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17705 .dac_nids = alc662_dac_nids,
Kailang Yang291702f2007-10-16 14:28:03 +020017706 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17707 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang291702f2007-10-16 14:28:03 +020017708 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017709 .setup = alc662_eeepc_setup,
Kailang Yang291702f2007-10-16 14:28:03 +020017710 .init_hook = alc662_eeepc_inithook,
17711 },
Kailang Yang8c427222008-01-10 13:03:59 +010017712 [ALC662_ASUS_EEEPC_EP20] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017713 .mixers = { alc662_eeepc_ep20_mixer,
Kailang Yang8c427222008-01-10 13:03:59 +010017714 alc662_chmode_mixer },
17715 .init_verbs = { alc662_init_verbs,
17716 alc662_eeepc_ep20_sue_init_verbs },
17717 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17718 .dac_nids = alc662_dac_nids,
Kailang Yang8c427222008-01-10 13:03:59 +010017719 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
17720 .channel_mode = alc662_3ST_6ch_modes,
17721 .input_mux = &alc662_lenovo_101e_capture_source,
Takashi Iwai42171c12009-05-08 14:11:43 +020017722 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017723 .setup = alc662_eeepc_ep20_setup,
Kailang Yang8c427222008-01-10 13:03:59 +010017724 .init_hook = alc662_eeepc_ep20_inithook,
17725 },
Kailang Yangf1d4e282008-08-26 14:03:29 +020017726 [ALC662_ECS] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017727 .mixers = { alc662_ecs_mixer },
Kailang Yangf1d4e282008-08-26 14:03:29 +020017728 .init_verbs = { alc662_init_verbs,
17729 alc662_ecs_init_verbs },
17730 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17731 .dac_nids = alc662_dac_nids,
17732 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17733 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017734 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017735 .setup = alc662_eeepc_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017736 .init_hook = alc662_eeepc_inithook,
17737 },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017738 [ALC663_ASUS_M51VA] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017739 .mixers = { alc663_m51va_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017740 .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
17741 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17742 .dac_nids = alc662_dac_nids,
17743 .dig_out_nid = ALC662_DIGOUT_NID,
17744 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17745 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017746 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017747 .setup = alc663_m51va_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017748 .init_hook = alc663_m51va_inithook,
17749 },
17750 [ALC663_ASUS_G71V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017751 .mixers = { alc663_g71v_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017752 .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
17753 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17754 .dac_nids = alc662_dac_nids,
17755 .dig_out_nid = ALC662_DIGOUT_NID,
17756 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17757 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017758 .unsol_event = alc663_g71v_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017759 .setup = alc663_g71v_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017760 .init_hook = alc663_g71v_inithook,
17761 },
17762 [ALC663_ASUS_H13] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017763 .mixers = { alc663_m51va_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017764 .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
17765 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17766 .dac_nids = alc662_dac_nids,
17767 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17768 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017769 .unsol_event = alc663_m51va_unsol_event,
17770 .init_hook = alc663_m51va_inithook,
17771 },
17772 [ALC663_ASUS_G50V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017773 .mixers = { alc663_g50v_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020017774 .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
17775 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17776 .dac_nids = alc662_dac_nids,
17777 .dig_out_nid = ALC662_DIGOUT_NID,
17778 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
17779 .channel_mode = alc662_3ST_6ch_modes,
17780 .input_mux = &alc663_capture_source,
17781 .unsol_event = alc663_g50v_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017782 .setup = alc663_g50v_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020017783 .init_hook = alc663_g50v_inithook,
17784 },
Kailang Yangf1d4e282008-08-26 14:03:29 +020017785 [ALC663_ASUS_MODE1] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017786 .mixers = { alc663_m51va_mixer },
17787 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017788 .init_verbs = { alc662_init_verbs,
17789 alc663_21jd_amic_init_verbs },
17790 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17791 .hp_nid = 0x03,
17792 .dac_nids = alc662_dac_nids,
17793 .dig_out_nid = ALC662_DIGOUT_NID,
17794 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17795 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017796 .unsol_event = alc663_mode1_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017797 .setup = alc663_mode1_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017798 .init_hook = alc663_mode1_inithook,
17799 },
17800 [ALC662_ASUS_MODE2] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017801 .mixers = { alc662_1bjd_mixer },
17802 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017803 .init_verbs = { alc662_init_verbs,
17804 alc662_1bjd_amic_init_verbs },
17805 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17806 .dac_nids = alc662_dac_nids,
17807 .dig_out_nid = ALC662_DIGOUT_NID,
17808 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17809 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017810 .unsol_event = alc662_mode2_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017811 .setup = alc662_mode2_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017812 .init_hook = alc662_mode2_inithook,
17813 },
17814 [ALC663_ASUS_MODE3] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017815 .mixers = { alc663_two_hp_m1_mixer },
17816 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017817 .init_verbs = { alc662_init_verbs,
17818 alc663_two_hp_amic_m1_init_verbs },
17819 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17820 .hp_nid = 0x03,
17821 .dac_nids = alc662_dac_nids,
17822 .dig_out_nid = ALC662_DIGOUT_NID,
17823 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17824 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017825 .unsol_event = alc663_mode3_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017826 .setup = alc663_mode3_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017827 .init_hook = alc663_mode3_inithook,
17828 },
17829 [ALC663_ASUS_MODE4] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017830 .mixers = { alc663_asus_21jd_clfe_mixer },
17831 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017832 .init_verbs = { alc662_init_verbs,
17833 alc663_21jd_amic_init_verbs},
17834 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17835 .hp_nid = 0x03,
17836 .dac_nids = alc662_dac_nids,
17837 .dig_out_nid = ALC662_DIGOUT_NID,
17838 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17839 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017840 .unsol_event = alc663_mode4_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017841 .setup = alc663_mode4_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017842 .init_hook = alc663_mode4_inithook,
17843 },
17844 [ALC663_ASUS_MODE5] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017845 .mixers = { alc663_asus_15jd_clfe_mixer },
17846 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017847 .init_verbs = { alc662_init_verbs,
17848 alc663_15jd_amic_init_verbs },
17849 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17850 .hp_nid = 0x03,
17851 .dac_nids = alc662_dac_nids,
17852 .dig_out_nid = ALC662_DIGOUT_NID,
17853 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17854 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017855 .unsol_event = alc663_mode5_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017856 .setup = alc663_mode5_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017857 .init_hook = alc663_mode5_inithook,
17858 },
17859 [ALC663_ASUS_MODE6] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010017860 .mixers = { alc663_two_hp_m2_mixer },
17861 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017862 .init_verbs = { alc662_init_verbs,
17863 alc663_two_hp_amic_m2_init_verbs },
17864 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17865 .hp_nid = 0x03,
17866 .dac_nids = alc662_dac_nids,
17867 .dig_out_nid = ALC662_DIGOUT_NID,
17868 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17869 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017870 .unsol_event = alc663_mode6_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017871 .setup = alc663_mode6_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020017872 .init_hook = alc663_mode6_inithook,
17873 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010017874 [ALC663_ASUS_MODE7] = {
17875 .mixers = { alc663_mode7_mixer },
17876 .cap_mixer = alc662_auto_capture_mixer,
17877 .init_verbs = { alc662_init_verbs,
17878 alc663_mode7_init_verbs },
17879 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17880 .hp_nid = 0x03,
17881 .dac_nids = alc662_dac_nids,
17882 .dig_out_nid = ALC662_DIGOUT_NID,
17883 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17884 .channel_mode = alc662_3ST_2ch_modes,
17885 .unsol_event = alc663_mode7_unsol_event,
17886 .setup = alc663_mode7_setup,
17887 .init_hook = alc663_mode7_inithook,
17888 },
17889 [ALC663_ASUS_MODE8] = {
17890 .mixers = { alc663_mode8_mixer },
17891 .cap_mixer = alc662_auto_capture_mixer,
17892 .init_verbs = { alc662_init_verbs,
17893 alc663_mode8_init_verbs },
17894 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
17895 .hp_nid = 0x03,
17896 .dac_nids = alc662_dac_nids,
17897 .dig_out_nid = ALC662_DIGOUT_NID,
17898 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17899 .channel_mode = alc662_3ST_2ch_modes,
17900 .unsol_event = alc663_mode8_unsol_event,
17901 .setup = alc663_mode8_setup,
17902 .init_hook = alc663_mode8_inithook,
17903 },
Kailang Yang622e84c2009-04-21 07:39:04 +020017904 [ALC272_DELL] = {
17905 .mixers = { alc663_m51va_mixer },
17906 .cap_mixer = alc272_auto_capture_mixer,
17907 .init_verbs = { alc662_init_verbs, alc272_dell_init_verbs },
17908 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
17909 .dac_nids = alc662_dac_nids,
17910 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17911 .adc_nids = alc272_adc_nids,
17912 .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
17913 .capsrc_nids = alc272_capsrc_nids,
17914 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang622e84c2009-04-21 07:39:04 +020017915 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017916 .setup = alc663_m51va_setup,
Kailang Yang622e84c2009-04-21 07:39:04 +020017917 .init_hook = alc663_m51va_inithook,
17918 },
17919 [ALC272_DELL_ZM1] = {
17920 .mixers = { alc663_m51va_mixer },
17921 .cap_mixer = alc662_auto_capture_mixer,
17922 .init_verbs = { alc662_init_verbs, alc272_dell_zm1_init_verbs },
17923 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
17924 .dac_nids = alc662_dac_nids,
17925 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17926 .adc_nids = alc662_adc_nids,
Takashi Iwaib59bdf32009-08-11 09:47:30 +020017927 .num_adc_nids = 1,
Kailang Yang622e84c2009-04-21 07:39:04 +020017928 .capsrc_nids = alc662_capsrc_nids,
17929 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang622e84c2009-04-21 07:39:04 +020017930 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017931 .setup = alc663_m51va_setup,
Kailang Yang622e84c2009-04-21 07:39:04 +020017932 .init_hook = alc663_m51va_inithook,
17933 },
Chris Pockelé9541ba12009-05-12 08:08:53 +020017934 [ALC272_SAMSUNG_NC10] = {
17935 .mixers = { alc272_nc10_mixer },
17936 .init_verbs = { alc662_init_verbs,
17937 alc663_21jd_amic_init_verbs },
17938 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
17939 .dac_nids = alc272_dac_nids,
17940 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
17941 .channel_mode = alc662_3ST_2ch_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017942 /*.input_mux = &alc272_nc10_capture_source,*/
Chris Pockelé9541ba12009-05-12 08:08:53 +020017943 .unsol_event = alc663_mode4_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017944 .setup = alc663_mode4_setup,
Chris Pockelé9541ba12009-05-12 08:08:53 +020017945 .init_hook = alc663_mode4_inithook,
17946 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017947};
17948
17949
17950/*
17951 * BIOS auto configuration
17952 */
17953
Takashi Iwai7085ec12009-10-02 09:03:58 +020017954/* convert from MIX nid to DAC */
17955static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
17956{
17957 if (nid == 0x0f)
17958 return 0x02;
17959 else if (nid >= 0x0c && nid <= 0x0e)
17960 return nid - 0x0c + 0x02;
17961 else
17962 return 0;
17963}
17964
17965/* get MIX nid connected to the given pin targeted to DAC */
17966static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
17967 hda_nid_t dac)
17968{
17969 hda_nid_t mix[4];
17970 int i, num;
17971
17972 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
17973 for (i = 0; i < num; i++) {
17974 if (alc662_mix_to_dac(mix[i]) == dac)
17975 return mix[i];
17976 }
17977 return 0;
17978}
17979
17980/* look for an empty DAC slot */
17981static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
17982{
17983 struct alc_spec *spec = codec->spec;
17984 hda_nid_t srcs[5];
17985 int i, j, num;
17986
17987 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
17988 if (num < 0)
17989 return 0;
17990 for (i = 0; i < num; i++) {
17991 hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
17992 if (!nid)
17993 continue;
17994 for (j = 0; j < spec->multiout.num_dacs; j++)
17995 if (spec->multiout.dac_nids[j] == nid)
17996 break;
17997 if (j >= spec->multiout.num_dacs)
17998 return nid;
17999 }
18000 return 0;
18001}
18002
18003/* fill in the dac_nids table from the parsed pin configuration */
18004static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
18005 const struct auto_pin_cfg *cfg)
18006{
18007 struct alc_spec *spec = codec->spec;
18008 int i;
18009 hda_nid_t dac;
18010
18011 spec->multiout.dac_nids = spec->private_dac_nids;
18012 for (i = 0; i < cfg->line_outs; i++) {
18013 dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
18014 if (!dac)
18015 continue;
18016 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
18017 }
18018 return 0;
18019}
18020
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018021static inline int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018022 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018023{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018024 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018025 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
18026}
18027
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018028static inline int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018029 hda_nid_t nid, unsigned int chs)
18030{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018031 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018032 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
18033}
18034
18035#define alc662_add_stereo_vol(spec, pfx, nid) \
18036 alc662_add_vol_ctl(spec, pfx, nid, 3)
18037#define alc662_add_stereo_sw(spec, pfx, nid) \
18038 alc662_add_sw_ctl(spec, pfx, nid, 3)
18039
18040/* add playback controls from the parsed DAC table */
18041static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
18042 const struct auto_pin_cfg *cfg)
18043{
18044 struct alc_spec *spec = codec->spec;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018045 static const char *chname[4] = {
18046 "Front", "Surround", NULL /*CLFE*/, "Side"
18047 };
Takashi Iwai7085ec12009-10-02 09:03:58 +020018048 hda_nid_t nid, mix;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018049 int i, err;
18050
18051 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018052 nid = spec->multiout.dac_nids[i];
18053 if (!nid)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018054 continue;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018055 mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
18056 if (!mix)
18057 continue;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018058 if (i == 2) {
18059 /* Center/LFE */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018060 err = alc662_add_vol_ctl(spec, "Center", nid, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018061 if (err < 0)
18062 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018063 err = alc662_add_vol_ctl(spec, "LFE", nid, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018064 if (err < 0)
18065 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018066 err = alc662_add_sw_ctl(spec, "Center", mix, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018067 if (err < 0)
18068 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018069 err = alc662_add_sw_ctl(spec, "LFE", mix, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018070 if (err < 0)
18071 return err;
18072 } else {
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018073 const char *pfx;
18074 if (cfg->line_outs == 1 &&
18075 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018076 if (cfg->hp_outs)
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018077 pfx = "Speaker";
18078 else
18079 pfx = "PCM";
18080 } else
18081 pfx = chname[i];
Takashi Iwai7085ec12009-10-02 09:03:58 +020018082 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018083 if (err < 0)
18084 return err;
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018085 if (cfg->line_outs == 1 &&
18086 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
18087 pfx = "Speaker";
Takashi Iwai7085ec12009-10-02 09:03:58 +020018088 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018089 if (err < 0)
18090 return err;
18091 }
18092 }
18093 return 0;
18094}
18095
18096/* add playback controls for speaker and HP outputs */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018097/* return DAC nid if any new DAC is assigned */
18098static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018099 const char *pfx)
18100{
Takashi Iwai7085ec12009-10-02 09:03:58 +020018101 struct alc_spec *spec = codec->spec;
18102 hda_nid_t nid, mix;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018103 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018104
18105 if (!pin)
18106 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018107 nid = alc662_look_for_dac(codec, pin);
18108 if (!nid) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018109 /* the corresponding DAC is already occupied */
18110 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
18111 return 0; /* no way */
18112 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018113 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018114 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
18115 }
18116
18117 mix = alc662_dac_to_mix(codec, pin, nid);
18118 if (!mix)
18119 return 0;
18120 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
18121 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +020018122 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018123 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
18124 if (err < 0)
18125 return err;
18126 return nid;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018127}
18128
18129/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020018130#define alc662_auto_create_input_ctls \
Takashi Iwai4b7348a2009-10-14 18:25:23 +020018131 alc882_auto_create_input_ctls
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018132
18133static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
18134 hda_nid_t nid, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018135 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018136{
Takashi Iwai7085ec12009-10-02 09:03:58 +020018137 int i, num;
18138 hda_nid_t srcs[4];
18139
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018140 alc_set_pin_output(codec, nid, pin_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018141 /* need the manual connection? */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018142 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
18143 if (num <= 1)
18144 return;
18145 for (i = 0; i < num; i++) {
18146 if (alc662_mix_to_dac(srcs[i]) != dac)
18147 continue;
18148 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
18149 return;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018150 }
18151}
18152
18153static void alc662_auto_init_multi_out(struct hda_codec *codec)
18154{
18155 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018156 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018157 int i;
18158
18159 for (i = 0; i <= HDA_SIDE; i++) {
18160 hda_nid_t nid = spec->autocfg.line_out_pins[i];
18161 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020018162 alc662_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018163 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018164 }
18165}
18166
18167static void alc662_auto_init_hp_out(struct hda_codec *codec)
18168{
18169 struct alc_spec *spec = codec->spec;
18170 hda_nid_t pin;
18171
18172 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +020018173 if (pin)
18174 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
18175 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018176 pin = spec->autocfg.speaker_pins[0];
18177 if (pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +020018178 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
18179 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018180}
18181
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018182#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
18183
18184static void alc662_auto_init_analog_input(struct hda_codec *codec)
18185{
18186 struct alc_spec *spec = codec->spec;
18187 int i;
18188
18189 for (i = 0; i < AUTO_PIN_LAST; i++) {
18190 hda_nid_t nid = spec->autocfg.input_pins[i];
Takashi Iwai05f5f472009-08-25 13:10:18 +020018191 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +010018192 alc_set_input_pin(codec, nid, i);
Takashi Iwai52ca15b2009-03-23 12:51:55 +010018193 if (nid != ALC662_PIN_CD_NID &&
Takashi Iwaie82c0252009-03-23 15:17:38 +010018194 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018195 snd_hda_codec_write(codec, nid, 0,
18196 AC_VERB_SET_AMP_GAIN_MUTE,
18197 AMP_OUT_MUTE);
18198 }
18199 }
18200}
18201
Takashi Iwaif511b012008-08-15 16:46:42 +020018202#define alc662_auto_init_input_src alc882_auto_init_input_src
18203
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018204static int alc662_parse_auto_config(struct hda_codec *codec)
18205{
18206 struct alc_spec *spec = codec->spec;
18207 int err;
18208 static hda_nid_t alc662_ignore[] = { 0x1d, 0 };
18209
18210 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
18211 alc662_ignore);
18212 if (err < 0)
18213 return err;
18214 if (!spec->autocfg.line_outs)
18215 return 0; /* can't find valid BIOS pin config */
18216
Takashi Iwai7085ec12009-10-02 09:03:58 +020018217 err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018218 if (err < 0)
18219 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018220 err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018221 if (err < 0)
18222 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018223 err = alc662_auto_create_extra_out(codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018224 spec->autocfg.speaker_pins[0],
18225 "Speaker");
18226 if (err < 0)
18227 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018228 if (err)
18229 spec->multiout.extra_out_nid[0] = err;
18230 err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018231 "Headphone");
18232 if (err < 0)
18233 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018234 if (err)
18235 spec->multiout.hp_nid = err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020018236 err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018237 if (err < 0)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018238 return err;
18239
18240 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
18241
Takashi Iwai0852d7a2009-02-11 11:35:15 +010018242 if (spec->autocfg.dig_outs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018243 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
18244
Takashi Iwai603c4012008-07-30 15:01:44 +020018245 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010018246 add_mixer(spec, spec->kctls.list);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018247
18248 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020018249 spec->input_mux = &spec->private_imux[0];
Kailang Yangea1fb292008-08-26 12:58:38 +020018250
Kailang Yangcec27c82010-02-04 14:18:18 +010018251 add_verb(spec, alc662_init_verbs);
18252 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
18253 codec->vendor_id == 0x10ec0665)
18254 add_verb(spec, alc663_init_verbs);
18255
18256 if (codec->vendor_id == 0x10ec0272)
18257 add_verb(spec, alc272_init_verbs);
Takashi Iwaiee979a142008-09-02 15:42:20 +020018258
18259 err = alc_auto_add_mic_boost(codec);
18260 if (err < 0)
18261 return err;
18262
Kailang Yang6227cdc2010-02-25 08:36:52 +010018263 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
18264 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
18265 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
18266 else
18267 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020018268
Takashi Iwai8c872862007-06-19 12:11:16 +020018269 return 1;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018270}
18271
18272/* additional initialization for auto-configuration model */
18273static void alc662_auto_init(struct hda_codec *codec)
18274{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018275 struct alc_spec *spec = codec->spec;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018276 alc662_auto_init_multi_out(codec);
18277 alc662_auto_init_hp_out(codec);
18278 alc662_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020018279 alc662_auto_init_input_src(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018280 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020018281 alc_inithook(codec);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018282}
18283
18284static int patch_alc662(struct hda_codec *codec)
18285{
18286 struct alc_spec *spec;
18287 int err, board_config;
18288
18289 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
18290 if (!spec)
18291 return -ENOMEM;
18292
18293 codec->spec = spec;
18294
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +020018295 alc_fix_pll_init(codec, 0x20, 0x04, 15);
18296
Kailang Yang274693f2009-12-03 10:07:50 +010018297 if (alc_read_coef_idx(codec, 0)==0x8020){
18298 kfree(codec->chip_name);
18299 codec->chip_name = kstrdup("ALC661", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018300 if (!codec->chip_name) {
18301 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010018302 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018303 }
Kailang Yang274693f2009-12-03 10:07:50 +010018304 }
18305
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018306 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
18307 alc662_models,
18308 alc662_cfg_tbl);
18309 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020018310 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
18311 codec->chip_name);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018312 board_config = ALC662_AUTO;
18313 }
18314
18315 if (board_config == ALC662_AUTO) {
18316 /* automatic parse from the BIOS config */
18317 err = alc662_parse_auto_config(codec);
18318 if (err < 0) {
18319 alc_free(codec);
18320 return err;
Takashi Iwai8c872862007-06-19 12:11:16 +020018321 } else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018322 printk(KERN_INFO
18323 "hda_codec: Cannot set up configuration "
18324 "from BIOS. Using base mode...\n");
18325 board_config = ALC662_3ST_2ch_DIG;
18326 }
18327 }
18328
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090018329 err = snd_hda_attach_beep_device(codec, 0x1);
18330 if (err < 0) {
18331 alc_free(codec);
18332 return err;
18333 }
18334
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018335 if (board_config != ALC662_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020018336 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018337
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018338 spec->stream_analog_playback = &alc662_pcm_analog_playback;
18339 spec->stream_analog_capture = &alc662_pcm_analog_capture;
18340
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018341 spec->stream_digital_playback = &alc662_pcm_digital_playback;
18342 spec->stream_digital_capture = &alc662_pcm_digital_capture;
18343
Takashi Iwaidd704692009-08-11 08:45:11 +020018344 if (!spec->adc_nids) {
18345 spec->adc_nids = alc662_adc_nids;
18346 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
18347 }
18348 if (!spec->capsrc_nids)
18349 spec->capsrc_nids = alc662_capsrc_nids;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018350
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018351 if (!spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020018352 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018353
Kailang Yangcec27c82010-02-04 14:18:18 +010018354 switch (codec->vendor_id) {
18355 case 0x10ec0662:
18356 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
18357 break;
18358 case 0x10ec0272:
18359 case 0x10ec0663:
18360 case 0x10ec0665:
18361 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
18362 break;
18363 case 0x10ec0273:
18364 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
18365 break;
18366 }
Takashi Iwai2134ea42008-01-10 16:53:55 +010018367 spec->vmaster_nid = 0x02;
18368
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018369 codec->patch_ops = alc_patch_ops;
18370 if (board_config == ALC662_AUTO)
18371 spec->init_hook = alc662_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020018372#ifdef CONFIG_SND_HDA_POWER_SAVE
18373 if (!spec->loopback.amplist)
18374 spec->loopback.amplist = alc662_loopbacks;
18375#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018376
18377 return 0;
18378}
18379
Kailang Yang274693f2009-12-03 10:07:50 +010018380static int patch_alc888(struct hda_codec *codec)
18381{
18382 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
18383 kfree(codec->chip_name);
18384 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018385 if (!codec->chip_name) {
18386 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010018387 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018388 }
18389 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010018390 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010018391 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010018392}
18393
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018394/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070018395 * patch entries
18396 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +010018397static struct hda_codec_preset snd_hda_preset_realtek[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070018398 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +010018399 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +010018400 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +020018401 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +010018402 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010018403 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +020018404 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010018405 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010018406 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018407 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010018408 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
18409 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
18410 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018411 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +020018412 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018413 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
18414 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +020018415 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +010018416 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +010018417 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010018418 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070018419 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +020018420 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +020018421 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +020018422 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +020018423 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +020018424 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +010018425 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +020018426 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
Kailang Yang44426082008-10-15 11:18:05 +020018427 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +020018428 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +010018429 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai49535502009-06-30 15:28:30 +020018430 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +010018431 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070018432 {} /* terminator */
18433};
Takashi Iwai1289e9e2008-11-27 15:47:11 +010018434
18435MODULE_ALIAS("snd-hda-codec-id:10ec*");
18436
18437MODULE_LICENSE("GPL");
18438MODULE_DESCRIPTION("Realtek HD-audio codec");
18439
18440static struct hda_codec_preset_list realtek_list = {
18441 .preset = snd_hda_preset_realtek,
18442 .owner = THIS_MODULE,
18443};
18444
18445static int __init patch_realtek_init(void)
18446{
18447 return snd_hda_add_codec_preset(&realtek_list);
18448}
18449
18450static void __exit patch_realtek_exit(void)
18451{
18452 snd_hda_delete_codec_preset(&realtek_list);
18453}
18454
18455module_init(patch_realtek_init)
18456module_exit(patch_realtek_exit)