blob: 3e0f4816aed786006550d64db10d136046e75b0b [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 Yangfe3eb0a2010-08-06 10:02:57 +0200140 ALC271_ACER,
Kailang Yangf6a92242007-12-13 16:52:54 +0100141 ALC269_AUTO,
142 ALC269_MODEL_LAST /* last tag */
143};
144
Kailang Yangdf694da2005-12-05 19:42:22 +0100145/* ALC861 models */
146enum {
147 ALC861_3ST,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200148 ALC660_3ST,
Kailang Yangdf694da2005-12-05 19:42:22 +0100149 ALC861_3ST_DIG,
150 ALC861_6ST_DIG,
Takashi Iwai22309c32006-08-09 16:57:28 +0200151 ALC861_UNIWILL_M31,
Tobin Davisa53d1ae2006-10-17 12:00:28 +0200152 ALC861_TOSHIBA,
Mariusz Domanski7cdbff92006-10-23 13:42:56 +0200153 ALC861_ASUS,
Takashi Iwai56bb0ca2006-11-22 11:52:52 +0100154 ALC861_ASUS_LAPTOP,
Kailang Yangdf694da2005-12-05 19:42:22 +0100155 ALC861_AUTO,
156 ALC861_MODEL_LAST,
157};
158
Jakub Schmidtkef32610e2007-02-02 18:17:27 +0100159/* ALC861-VD models */
160enum {
161 ALC660VD_3ST,
Mike Crash6963f842007-06-25 12:12:51 +0200162 ALC660VD_3ST_DIG,
Takashi Iwai13c94742008-11-05 08:06:08 +0100163 ALC660VD_ASUS_V1S,
Jakub Schmidtkef32610e2007-02-02 18:17:27 +0100164 ALC861VD_3ST,
165 ALC861VD_3ST_DIG,
166 ALC861VD_6ST_DIG,
Kailang Yangbdd148a2007-05-08 15:19:08 +0200167 ALC861VD_LENOVO,
Kailang Yang272a5272007-05-14 11:00:38 +0200168 ALC861VD_DALLAS,
Kailang Yangd1a991a2007-08-15 16:21:59 +0200169 ALC861VD_HP,
Jakub Schmidtkef32610e2007-02-02 18:17:27 +0100170 ALC861VD_AUTO,
171 ALC861VD_MODEL_LAST,
172};
173
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200174/* ALC662 models */
175enum {
176 ALC662_3ST_2ch_DIG,
177 ALC662_3ST_6ch_DIG,
178 ALC662_3ST_6ch,
179 ALC662_5ST_DIG,
180 ALC662_LENOVO_101E,
Kailang Yang291702f2007-10-16 14:28:03 +0200181 ALC662_ASUS_EEEPC_P701,
Kailang Yang8c427222008-01-10 13:03:59 +0100182 ALC662_ASUS_EEEPC_EP20,
Kailang Yang6dda9f42008-05-27 12:05:31 +0200183 ALC663_ASUS_M51VA,
184 ALC663_ASUS_G71V,
185 ALC663_ASUS_H13,
186 ALC663_ASUS_G50V,
Kailang Yangf1d4e282008-08-26 14:03:29 +0200187 ALC662_ECS,
188 ALC663_ASUS_MODE1,
189 ALC662_ASUS_MODE2,
190 ALC663_ASUS_MODE3,
191 ALC663_ASUS_MODE4,
192 ALC663_ASUS_MODE5,
193 ALC663_ASUS_MODE6,
Kailang Yangebb83ee2009-12-17 12:23:00 +0100194 ALC663_ASUS_MODE7,
195 ALC663_ASUS_MODE8,
Kailang Yang622e84c2009-04-21 07:39:04 +0200196 ALC272_DELL,
197 ALC272_DELL_ZM1,
Chris Pockelé9541ba12009-05-12 08:08:53 +0200198 ALC272_SAMSUNG_NC10,
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200199 ALC662_AUTO,
200 ALC662_MODEL_LAST,
201};
202
Kailang Yangdf694da2005-12-05 19:42:22 +0100203/* ALC882 models */
204enum {
205 ALC882_3ST_DIG,
206 ALC882_6ST_DIG,
Takashi Iwai4b146cb2006-07-28 14:42:36 +0200207 ALC882_ARIMA,
Kailang Yangbdd148a2007-05-08 15:19:08 +0200208 ALC882_W2JC,
Kailang Yang272a5272007-05-14 11:00:38 +0200209 ALC882_TARGA,
210 ALC882_ASUS_A7J,
Takashi Iwai914759b2007-09-06 14:52:04 +0200211 ALC882_ASUS_A7M,
Tobin Davis9102cd12006-12-15 10:02:12 +0100212 ALC885_MACPRO,
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -0800213 ALC885_MBA21,
Takashi Iwai87350ad2007-08-16 18:19:38 +0200214 ALC885_MBP3,
Kacper Szczesniak41d55452009-05-07 12:47:43 +0200215 ALC885_MB5,
Luke Yelaviche458b1f2010-02-12 16:28:29 +1100216 ALC885_MACMINI3,
Nicola Fagnanic54728d2007-07-19 23:28:52 +0200217 ALC885_IMAC24,
Justin P. Mattock4b7e1802009-12-07 15:07:46 -0800218 ALC885_IMAC91,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200219 ALC883_3ST_2ch_DIG,
220 ALC883_3ST_6ch_DIG,
221 ALC883_3ST_6ch,
222 ALC883_6ST_DIG,
Kailang Yangccc656c2006-10-17 12:32:26 +0200223 ALC883_TARGA_DIG,
224 ALC883_TARGA_2ch_DIG,
David Heidelberger64a8be72009-06-08 16:15:18 +0200225 ALC883_TARGA_8ch_DIG,
Vladimir Avdoninbab282b2006-08-22 13:31:58 +0200226 ALC883_ACER,
Tobin Davis2880a862007-08-07 11:50:26 +0200227 ALC883_ACER_ASPIRE,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +0800228 ALC888_ACER_ASPIRE_4930G,
Tony Vroond2fd4b02009-06-21 00:40:10 +0100229 ALC888_ACER_ASPIRE_6530G,
Hector Martin3b315d72009-06-02 10:54:19 +0200230 ALC888_ACER_ASPIRE_8930G,
Denis Kuplyakovfc86f952009-08-25 18:15:59 +0200231 ALC888_ACER_ASPIRE_7730G,
Tobin Davisc07584c2006-10-13 12:32:16 +0200232 ALC883_MEDION,
Kailang Yangea1fb292008-08-26 12:58:38 +0200233 ALC883_MEDION_MD2,
Maurus Cuelenaere7ad7b212010-04-06 18:12:52 +0200234 ALC883_MEDION_WIM2160,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +0100235 ALC883_LAPTOP_EAPD,
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200236 ALC883_LENOVO_101E_2ch,
Kailang Yang272a5272007-05-14 11:00:38 +0200237 ALC883_LENOVO_NB0763,
Kailang Yang189609a2007-08-20 11:31:23 +0200238 ALC888_LENOVO_MS7195_DIG,
Kailang Yange2757d52008-08-26 13:17:46 +0200239 ALC888_LENOVO_SKY,
Kailang Yangea1fb292008-08-26 12:58:38 +0200240 ALC883_HAIER_W66,
Claudio Matsuoka4723c022007-07-13 14:36:19 +0200241 ALC888_3ST_HP,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +0100242 ALC888_6ST_DELL,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +0100243 ALC883_MITAC,
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -0430244 ALC883_CLEVO_M540R,
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +0100245 ALC883_CLEVO_M720,
Jiang zhefb97dc62008-03-06 11:07:11 +0100246 ALC883_FUJITSU_PI2515,
Vincent Petryef8ef5f2008-11-23 11:31:41 +0800247 ALC888_FUJITSU_XA3530,
Jiang zhe17bba1b2008-06-04 12:11:07 +0200248 ALC883_3ST_6ch_INTEL,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200249 ALC889A_INTEL,
250 ALC889_INTEL,
Kailang Yange2757d52008-08-26 13:17:46 +0200251 ALC888_ASUS_M90V,
252 ALC888_ASUS_EEE1601,
Torben Schulzeb4c41d2009-05-18 15:02:35 +0200253 ALC889A_MB31,
Wu Fengguang3ab90932008-11-17 09:51:09 +0100254 ALC1200_ASUS_P5Q,
Guido Günther3e1647c2009-06-05 00:47:26 +0200255 ALC883_SONY_VAIO_TT,
Takashi Iwai49535502009-06-30 15:28:30 +0200256 ALC882_AUTO,
257 ALC882_MODEL_LAST,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200258};
259
Takashi Iwaid4a86d82010-06-23 17:51:26 +0200260/* ALC680 models */
261enum {
262 ALC680_BASE,
263 ALC680_AUTO,
264 ALC680_MODEL_LAST,
265};
266
Kailang Yangdf694da2005-12-05 19:42:22 +0100267/* for GPIO Poll */
268#define GPIO_MASK 0x03
269
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200270/* extra amp-initialization sequence types */
271enum {
272 ALC_INIT_NONE,
273 ALC_INIT_DEFAULT,
274 ALC_INIT_GPIO1,
275 ALC_INIT_GPIO2,
276 ALC_INIT_GPIO3,
277};
278
Takashi Iwai6c819492009-08-10 18:47:44 +0200279struct alc_mic_route {
280 hda_nid_t pin;
281 unsigned char mux_idx;
282 unsigned char amix_idx;
283};
284
285#define MUX_IDX_UNDEF ((unsigned char)-1)
286
Kailang Yangda00c242010-03-19 11:23:45 +0100287struct alc_customize_define {
288 unsigned int sku_cfg;
289 unsigned char port_connectivity;
290 unsigned char check_sum;
291 unsigned char customization;
292 unsigned char external_amp;
293 unsigned int enable_pcbeep:1;
294 unsigned int platform_type:1;
295 unsigned int swap:1;
296 unsigned int override:1;
297};
298
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299struct alc_spec {
300 /* codec parameterization */
Kailang Yangdf694da2005-12-05 19:42:22 +0100301 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 unsigned int num_mixers;
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100303 struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100304 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Takashi Iwai2d9c6482009-10-13 08:06:55 +0200306 const struct hda_verb *init_verbs[10]; /* initialization verbs
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200307 * don't forget NULL
308 * termination!
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200309 */
310 unsigned int num_init_verbs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200312 char stream_name_analog[32]; /* analog PCM stream */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 struct hda_pcm_stream *stream_analog_playback;
314 struct hda_pcm_stream *stream_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +0100315 struct hda_pcm_stream *stream_analog_alt_playback;
316 struct hda_pcm_stream *stream_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
Takashi Iwaiaa563af2009-07-31 10:05:11 +0200318 char stream_name_digital[32]; /* digital PCM stream */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 struct hda_pcm_stream *stream_digital_playback;
320 struct hda_pcm_stream *stream_digital_capture;
321
322 /* playback */
Takashi Iwai16ded522005-06-10 19:58:24 +0200323 struct hda_multi_out multiout; /* playback set-up
324 * max_channels, dacs must be set
325 * dig_out_nid and hp_nid are optional
326 */
Takashi Iwai63300792008-01-24 15:31:36 +0100327 hda_nid_t alt_dac_nid;
Takashi Iwai6a05ac42009-02-13 11:19:09 +0100328 hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */
Takashi Iwai8c441982009-01-20 18:30:20 +0100329 int dig_out_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330
331 /* capture */
332 unsigned int num_adc_nids;
333 hda_nid_t *adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100334 hda_nid_t *capsrc_nids;
Takashi Iwai16ded522005-06-10 19:58:24 +0200335 hda_nid_t dig_in_nid; /* digital-in NID; optional */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Takashi Iwai840b64c2010-07-13 22:49:01 +0200337 /* capture setup for dynamic dual-adc switch */
338 unsigned int cur_adc_idx;
339 hda_nid_t cur_adc;
340 unsigned int cur_adc_stream_tag;
341 unsigned int cur_adc_format;
342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 /* capture source */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200344 unsigned int num_mux_defs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 const struct hda_input_mux *input_mux;
346 unsigned int cur_mux[3];
Takashi Iwai6c819492009-08-10 18:47:44 +0200347 struct alc_mic_route ext_mic;
348 struct alc_mic_route int_mic;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350 /* channel model */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100351 const struct hda_channel_mode *channel_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 int num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200353 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200354 int const_channel_count;
355 int ext_channel_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357 /* PCM information */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100358 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
Takashi Iwai41e41f12005-06-08 14:48:49 +0200359
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200360 /* dynamic controls, init_verbs and input_mux */
361 struct auto_pin_cfg autocfg;
Kailang Yangda00c242010-03-19 11:23:45 +0100362 struct alc_customize_define cdefine;
Takashi Iwai603c4012008-07-30 15:01:44 +0200363 struct snd_array kctls;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -0200364 struct hda_input_mux private_imux[3];
Takashi Iwai41923e42007-10-22 17:20:10 +0200365 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai49535502009-06-30 15:28:30 +0200366 hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
367 hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
Takashi Iwai834be882006-03-01 14:16:17 +0100368
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100369 /* hooks */
370 void (*init_hook)(struct hda_codec *codec);
371 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
Hector Martinf5de24b2009-12-20 22:51:31 +0100372#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -0500373 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100374#endif
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100375
Takashi Iwai834be882006-03-01 14:16:17 +0100376 /* for pin sensing */
377 unsigned int sense_updated: 1;
378 unsigned int jack_present: 1;
Takashi Iwaibec15c32008-01-28 18:16:30 +0100379 unsigned int master_sw: 1;
Takashi Iwai6c819492009-08-10 18:47:44 +0200380 unsigned int auto_mic:1;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200381
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100382 /* other flags */
383 unsigned int no_analog :1; /* digital I/O only */
Takashi Iwai840b64c2010-07-13 22:49:01 +0200384 unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200385 int init_amp;
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100386
Takashi Iwai2134ea42008-01-10 16:53:55 +0100387 /* for virtual master */
388 hda_nid_t vmaster_nid;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200389#ifdef CONFIG_SND_HDA_POWER_SAVE
390 struct hda_loopback_check loopback;
391#endif
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200392
393 /* for PLL fix */
394 hda_nid_t pll_nid;
395 unsigned int pll_coef_idx, pll_coef_bit;
Kailang Yangdf694da2005-12-05 19:42:22 +0100396};
397
398/*
399 * configuration template - to be copied to the spec instance
400 */
401struct alc_config_preset {
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200402 struct snd_kcontrol_new *mixers[5]; /* should be identical size
403 * with spec
404 */
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100405 struct snd_kcontrol_new *cap_mixer; /* capture mixer */
Kailang Yangdf694da2005-12-05 19:42:22 +0100406 const struct hda_verb *init_verbs[5];
407 unsigned int num_dacs;
408 hda_nid_t *dac_nids;
409 hda_nid_t dig_out_nid; /* optional */
410 hda_nid_t hp_nid; /* optional */
Wu Fengguangb25c9da2009-02-06 15:02:27 +0800411 hda_nid_t *slave_dig_outs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100412 unsigned int num_adc_nids;
413 hda_nid_t *adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100414 hda_nid_t *capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +0100415 hda_nid_t dig_in_nid;
416 unsigned int num_channel_mode;
417 const struct hda_channel_mode *channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200418 int need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200419 int const_channel_count;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200420 unsigned int num_mux_defs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100421 const struct hda_input_mux *input_mux;
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100422 void (*unsol_event)(struct hda_codec *, unsigned int);
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200423 void (*setup)(struct hda_codec *);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100424 void (*init_hook)(struct hda_codec *);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200425#ifdef CONFIG_SND_HDA_POWER_SAVE
426 struct hda_amp_list *loopbacks;
Daniel T Chenc97259d2009-12-27 18:52:08 -0500427 void (*power_hook)(struct hda_codec *codec);
Takashi Iwaicb53c622007-08-10 17:21:45 +0200428#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429};
430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
432/*
433 * input MUX handling
434 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200435static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
436 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
438 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
439 struct alc_spec *spec = codec->spec;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200440 unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
441 if (mux_idx >= spec->num_mux_defs)
442 mux_idx = 0;
Takashi Iwai53111142010-03-08 12:13:07 +0100443 if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
444 mux_idx = 0;
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200445 return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200448static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
449 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450{
451 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
452 struct alc_spec *spec = codec->spec;
453 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
454
455 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
456 return 0;
457}
458
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200459static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
460 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
462 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
463 struct alc_spec *spec = codec->spec;
Takashi Iwaicd896c32008-11-18 12:36:33 +0100464 const struct hda_input_mux *imux;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaicd896c32008-11-18 12:36:33 +0100466 unsigned int mux_idx;
Takashi Iwaie1406342008-02-11 18:32:32 +0100467 hda_nid_t nid = spec->capsrc_nids ?
468 spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200469 unsigned int type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
Takashi Iwaicd896c32008-11-18 12:36:33 +0100471 mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
472 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +0100473 if (!imux->num_items && mux_idx > 0)
474 imux = &spec->input_mux[0];
Takashi Iwaicd896c32008-11-18 12:36:33 +0100475
Takashi Iwaia22d5432009-07-27 12:54:26 +0200476 type = get_wcaps_type(get_wcaps(codec, nid));
Takashi Iwai0169b6b2009-06-22 10:50:19 +0200477 if (type == AC_WID_AUD_MIX) {
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100478 /* Matrix-mixer style (e.g. ALC882) */
479 unsigned int *cur_val = &spec->cur_mux[adc_idx];
480 unsigned int i, idx;
481
482 idx = ucontrol->value.enumerated.item[0];
483 if (idx >= imux->num_items)
484 idx = imux->num_items - 1;
485 if (*cur_val == idx)
486 return 0;
487 for (i = 0; i < imux->num_items; i++) {
488 unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
489 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
490 imux->items[i].index,
491 HDA_AMP_MUTE, v);
492 }
493 *cur_val = idx;
494 return 1;
495 } else {
496 /* MUX style (e.g. ALC880) */
Takashi Iwaicd896c32008-11-18 12:36:33 +0100497 return snd_hda_input_mux_put(codec, imux, ucontrol, nid,
Takashi Iwai54cbc9a2008-10-31 15:24:04 +0100498 &spec->cur_mux[adc_idx]);
499 }
500}
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502/*
503 * channel mode setting
504 */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200505static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
506 struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507{
508 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
509 struct alc_spec *spec = codec->spec;
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100510 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
511 spec->num_channel_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512}
513
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200514static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
515 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516{
517 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
518 struct alc_spec *spec = codec->spec;
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +0100519 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200520 spec->num_channel_mode,
Hector Martin3b315d72009-06-02 10:54:19 +0200521 spec->ext_channel_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522}
523
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200524static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
525 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
527 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
528 struct alc_spec *spec = codec->spec;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200529 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
530 spec->num_channel_mode,
Hector Martin3b315d72009-06-02 10:54:19 +0200531 &spec->ext_channel_count);
532 if (err >= 0 && !spec->const_channel_count) {
533 spec->multiout.max_channels = spec->ext_channel_count;
534 if (spec->need_dac_fix)
535 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
536 }
Takashi Iwai4e195a72006-07-28 14:47:34 +0200537 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538}
539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540/*
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100541 * Control the mode of pin widget settings via the mixer. "pc" is used
Kailang Yangea1fb292008-08-26 12:58:38 +0200542 * instead of "%" to avoid consequences of accidently treating the % as
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100543 * being part of a format specifier. Maximum allowed length of a value is
544 * 63 characters plus NULL terminator.
Jonathan Woithe7cf51e42006-02-09 12:01:26 +0100545 *
546 * Note: some retasking pin complexes seem to ignore requests for input
547 * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
548 * are requested. Therefore order this list so that this behaviour will not
549 * cause problems when mixer clients move through the enum sequentially.
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200550 * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
551 * March 2006.
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200552 */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100553static char *alc_pin_mode_names[] = {
Jonathan Woithe7cf51e42006-02-09 12:01:26 +0100554 "Mic 50pc bias", "Mic 80pc bias",
555 "Line in", "Line out", "Headphone out",
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100556};
557static unsigned char alc_pin_mode_values[] = {
Jonathan Woithe7cf51e42006-02-09 12:01:26 +0100558 PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100559};
560/* The control can present all 5 options, or it can limit the options based
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200561 * in the pin being assumed to be exclusively an input or an output pin. In
562 * addition, "input" pins may or may not process the mic bias option
563 * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
564 * accept requests for bias as of chip versions up to March 2006) and/or
565 * wiring in the computer.
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100566 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200567#define ALC_PIN_DIR_IN 0x00
568#define ALC_PIN_DIR_OUT 0x01
569#define ALC_PIN_DIR_INOUT 0x02
570#define ALC_PIN_DIR_IN_NOMICBIAS 0x03
571#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100572
Kailang Yangea1fb292008-08-26 12:58:38 +0200573/* Info about the pin modes supported by the different pin direction modes.
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100574 * For each direction the minimum and maximum values are given.
575 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200576static signed char alc_pin_mode_dir_info[5][2] = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100577 { 0, 2 }, /* ALC_PIN_DIR_IN */
578 { 3, 4 }, /* ALC_PIN_DIR_OUT */
579 { 0, 4 }, /* ALC_PIN_DIR_INOUT */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200580 { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
581 { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100582};
583#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
584#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
585#define alc_pin_mode_n_items(_dir) \
586 (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
587
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200588static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
589 struct snd_ctl_elem_info *uinfo)
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200590{
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100591 unsigned int item_num = uinfo->value.enumerated.item;
592 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
593
594 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200595 uinfo->count = 1;
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100596 uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
597
598 if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
599 item_num = alc_pin_mode_min(dir);
600 strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200601 return 0;
602}
603
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200604static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
605 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200606{
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100607 unsigned int i;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200608 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
609 hda_nid_t nid = kcontrol->private_value & 0xffff;
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100610 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200611 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200612 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
613 AC_VERB_GET_PIN_WIDGET_CONTROL,
614 0x00);
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200615
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100616 /* Find enumerated value for current pinctl setting */
617 i = alc_pin_mode_min(dir);
Roel Kluin4b35d2c2009-08-02 13:30:45 +0200618 while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100619 i++;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200620 *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100621 return 0;
622}
623
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200624static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
625 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100626{
627 signed int change;
628 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
629 hda_nid_t nid = kcontrol->private_value & 0xffff;
630 unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
631 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200632 unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
633 AC_VERB_GET_PIN_WIDGET_CONTROL,
634 0x00);
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100635
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200636 if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100637 val = alc_pin_mode_min(dir);
638
639 change = pinctl != alc_pin_mode_values[val];
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100640 if (change) {
641 /* Set pin mode to that requested */
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200642 snd_hda_codec_write_cache(codec, nid, 0,
643 AC_VERB_SET_PIN_WIDGET_CONTROL,
644 alc_pin_mode_values[val]);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100645
Kailang Yangea1fb292008-08-26 12:58:38 +0200646 /* Also enable the retasking pin's input/output as required
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100647 * for the requested pin mode. Enum values of 2 or less are
648 * input modes.
649 *
650 * Dynamically switching the input/output buffers probably
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200651 * reduces noise slightly (particularly on input) so we'll
652 * do it. However, having both input and output buffers
653 * enabled simultaneously doesn't seem to be problematic if
654 * this turns out to be necessary in the future.
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100655 */
656 if (val <= 2) {
Takashi Iwai47fd8302007-08-10 17:11:07 +0200657 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
658 HDA_AMP_MUTE, HDA_AMP_MUTE);
659 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
660 HDA_AMP_MUTE, 0);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100661 } else {
Takashi Iwai47fd8302007-08-10 17:11:07 +0200662 snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
663 HDA_AMP_MUTE, HDA_AMP_MUTE);
664 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
665 HDA_AMP_MUTE, 0);
Jonathan Woithecdcd9262006-02-28 11:36:42 +0100666 }
667 }
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200668 return change;
669}
670
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100671#define ALC_PIN_MODE(xname, nid, dir) \
Jonathan Woithea9430dd2005-09-16 19:12:48 +0200672 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100673 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe4c5186e2006-02-09 11:53:48 +0100674 .info = alc_pin_mode_info, \
675 .get = alc_pin_mode_get, \
676 .put = alc_pin_mode_put, \
677 .private_value = nid | (dir<<16) }
Kailang Yangdf694da2005-12-05 19:42:22 +0100678
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100679/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
680 * together using a mask with more than one bit set. This control is
681 * currently used only by the ALC260 test model. At this stage they are not
682 * needed for any "production" models.
683 */
684#ifdef CONFIG_SND_DEBUG
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200685#define alc_gpio_data_info snd_ctl_boolean_mono_info
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200686
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200687static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
688 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100689{
690 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
691 hda_nid_t nid = kcontrol->private_value & 0xffff;
692 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
693 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200694 unsigned int val = snd_hda_codec_read(codec, nid, 0,
695 AC_VERB_GET_GPIO_DATA, 0x00);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100696
697 *valp = (val & mask) != 0;
698 return 0;
699}
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200700static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
701 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100702{
703 signed int change;
704 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
705 hda_nid_t nid = kcontrol->private_value & 0xffff;
706 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
707 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200708 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
709 AC_VERB_GET_GPIO_DATA,
710 0x00);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100711
712 /* Set/unset the masked GPIO bit(s) as needed */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200713 change = (val == 0 ? 0 : mask) != (gpio_data & mask);
714 if (val == 0)
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100715 gpio_data &= ~mask;
716 else
717 gpio_data |= mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200718 snd_hda_codec_write_cache(codec, nid, 0,
719 AC_VERB_SET_GPIO_DATA, gpio_data);
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100720
721 return change;
722}
723#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
724 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100725 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe5c8f8582006-02-28 11:43:27 +0100726 .info = alc_gpio_data_info, \
727 .get = alc_gpio_data_get, \
728 .put = alc_gpio_data_put, \
729 .private_value = nid | (mask<<16) }
730#endif /* CONFIG_SND_DEBUG */
731
Jonathan Woithe92621f12006-02-28 11:47:47 +0100732/* A switch control to allow the enabling of the digital IO pins on the
733 * ALC260. This is incredibly simplistic; the intention of this control is
734 * to provide something in the test model allowing digital outputs to be
735 * identified if present. If models are found which can utilise these
736 * outputs a more complete mixer control can be devised for those models if
737 * necessary.
738 */
739#ifdef CONFIG_SND_DEBUG
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200740#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200741
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200742static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
743 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe92621f12006-02-28 11:47:47 +0100744{
745 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
746 hda_nid_t nid = kcontrol->private_value & 0xffff;
747 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
748 long *valp = ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200749 unsigned int val = snd_hda_codec_read(codec, nid, 0,
Andrew Paprocki3982d172007-12-19 12:13:44 +0100750 AC_VERB_GET_DIGI_CONVERT_1, 0x00);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100751
752 *valp = (val & mask) != 0;
753 return 0;
754}
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200755static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
756 struct snd_ctl_elem_value *ucontrol)
Jonathan Woithe92621f12006-02-28 11:47:47 +0100757{
758 signed int change;
759 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
760 hda_nid_t nid = kcontrol->private_value & 0xffff;
761 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
762 long val = *ucontrol->value.integer.value;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200763 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
Andrew Paprocki3982d172007-12-19 12:13:44 +0100764 AC_VERB_GET_DIGI_CONVERT_1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200765 0x00);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100766
767 /* Set/unset the masked control bit(s) as needed */
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200768 change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100769 if (val==0)
770 ctrl_data &= ~mask;
771 else
772 ctrl_data |= mask;
Takashi Iwai82beb8f2007-08-10 17:09:26 +0200773 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
774 ctrl_data);
Jonathan Woithe92621f12006-02-28 11:47:47 +0100775
776 return change;
777}
778#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
779 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100780 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithe92621f12006-02-28 11:47:47 +0100781 .info = alc_spdif_ctrl_info, \
782 .get = alc_spdif_ctrl_get, \
783 .put = alc_spdif_ctrl_put, \
784 .private_value = nid | (mask<<16) }
785#endif /* CONFIG_SND_DEBUG */
786
Jonathan Woithef8225f62008-01-08 12:16:54 +0100787/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
788 * Again, this is only used in the ALC26x test models to help identify when
789 * the EAPD line must be asserted for features to work.
790 */
791#ifdef CONFIG_SND_DEBUG
792#define alc_eapd_ctrl_info snd_ctl_boolean_mono_info
793
794static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
795 struct snd_ctl_elem_value *ucontrol)
796{
797 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
798 hda_nid_t nid = kcontrol->private_value & 0xffff;
799 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
800 long *valp = ucontrol->value.integer.value;
801 unsigned int val = snd_hda_codec_read(codec, nid, 0,
802 AC_VERB_GET_EAPD_BTLENABLE, 0x00);
803
804 *valp = (val & mask) != 0;
805 return 0;
806}
807
808static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
809 struct snd_ctl_elem_value *ucontrol)
810{
811 int change;
812 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
813 hda_nid_t nid = kcontrol->private_value & 0xffff;
814 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
815 long val = *ucontrol->value.integer.value;
816 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
817 AC_VERB_GET_EAPD_BTLENABLE,
818 0x00);
819
820 /* Set/unset the masked control bit(s) as needed */
821 change = (!val ? 0 : mask) != (ctrl_data & mask);
822 if (!val)
823 ctrl_data &= ~mask;
824 else
825 ctrl_data |= mask;
826 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
827 ctrl_data);
828
829 return change;
830}
831
832#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
833 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +0100834 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Jonathan Woithef8225f62008-01-08 12:16:54 +0100835 .info = alc_eapd_ctrl_info, \
836 .get = alc_eapd_ctrl_get, \
837 .put = alc_eapd_ctrl_put, \
838 .private_value = nid | (mask<<16) }
839#endif /* CONFIG_SND_DEBUG */
840
Kailang Yangdf694da2005-12-05 19:42:22 +0100841/*
Takashi Iwai23f0c042009-02-26 13:03:58 +0100842 * set up the input pin config (depending on the given auto-pin type)
843 */
844static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
845 int auto_pin_type)
846{
847 unsigned int val = PIN_IN;
848
849 if (auto_pin_type <= AUTO_PIN_FRONT_MIC) {
850 unsigned int pincap;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200851 unsigned int oldval;
852 oldval = snd_hda_codec_read(codec, nid, 0,
853 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwai1327a322009-03-23 13:07:47 +0100854 pincap = snd_hda_query_pin_caps(codec, nid);
Takashi Iwai23f0c042009-02-26 13:03:58 +0100855 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
Takashi Iwai954a29c2010-07-30 10:55:44 +0200856 /* if the default pin setup is vref50, we give it priority */
857 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
Takashi Iwai23f0c042009-02-26 13:03:58 +0100858 val = PIN_VREF80;
Takashi Iwai461c6c32009-05-25 08:06:02 +0200859 else if (pincap & AC_PINCAP_VREF_50)
860 val = PIN_VREF50;
861 else if (pincap & AC_PINCAP_VREF_100)
862 val = PIN_VREF100;
863 else if (pincap & AC_PINCAP_VREF_GRD)
864 val = PIN_VREFGRD;
Takashi Iwai23f0c042009-02-26 13:03:58 +0100865 }
866 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
867}
868
869/*
Takashi Iwaid88897e2008-10-31 15:01:37 +0100870 */
871static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
872{
873 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
874 return;
875 spec->mixers[spec->num_mixers++] = mix;
876}
877
878static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
879{
880 if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
881 return;
882 spec->init_verbs[spec->num_init_verbs++] = verb;
883}
884
885/*
Kailang Yangdf694da2005-12-05 19:42:22 +0100886 * set up from the preset table
887 */
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200888static void setup_preset(struct hda_codec *codec,
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200889 const struct alc_config_preset *preset)
Kailang Yangdf694da2005-12-05 19:42:22 +0100890{
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200891 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +0100892 int i;
893
894 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100895 add_mixer(spec, preset->mixers[i]);
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100896 spec->cap_mixer = preset->cap_mixer;
Takashi Iwai9c7f8522006-06-28 15:08:22 +0200897 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
898 i++)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100899 add_verb(spec, preset->init_verbs[i]);
Kailang Yangea1fb292008-08-26 12:58:38 +0200900
Kailang Yangdf694da2005-12-05 19:42:22 +0100901 spec->channel_mode = preset->channel_mode;
902 spec->num_channel_mode = preset->num_channel_mode;
Takashi Iwai4e195a72006-07-28 14:47:34 +0200903 spec->need_dac_fix = preset->need_dac_fix;
Hector Martin3b315d72009-06-02 10:54:19 +0200904 spec->const_channel_count = preset->const_channel_count;
Kailang Yangdf694da2005-12-05 19:42:22 +0100905
Hector Martin3b315d72009-06-02 10:54:19 +0200906 if (preset->const_channel_count)
907 spec->multiout.max_channels = preset->const_channel_count;
908 else
909 spec->multiout.max_channels = spec->channel_mode[0].channels;
910 spec->ext_channel_count = spec->channel_mode[0].channels;
Kailang Yangdf694da2005-12-05 19:42:22 +0100911
912 spec->multiout.num_dacs = preset->num_dacs;
913 spec->multiout.dac_nids = preset->dac_nids;
914 spec->multiout.dig_out_nid = preset->dig_out_nid;
Wu Fengguangb25c9da2009-02-06 15:02:27 +0800915 spec->multiout.slave_dig_outs = preset->slave_dig_outs;
Kailang Yangdf694da2005-12-05 19:42:22 +0100916 spec->multiout.hp_nid = preset->hp_nid;
Kailang Yangea1fb292008-08-26 12:58:38 +0200917
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200918 spec->num_mux_defs = preset->num_mux_defs;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +0200919 if (!spec->num_mux_defs)
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +0200920 spec->num_mux_defs = 1;
Kailang Yangdf694da2005-12-05 19:42:22 +0100921 spec->input_mux = preset->input_mux;
922
923 spec->num_adc_nids = preset->num_adc_nids;
924 spec->adc_nids = preset->adc_nids;
Takashi Iwaie1406342008-02-11 18:32:32 +0100925 spec->capsrc_nids = preset->capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +0100926 spec->dig_in_nid = preset->dig_in_nid;
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100927
928 spec->unsol_event = preset->unsol_event;
929 spec->init_hook = preset->init_hook;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200930#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +0100931 spec->power_hook = preset->power_hook;
Takashi Iwaicb53c622007-08-10 17:21:45 +0200932 spec->loopback.amplist = preset->loopbacks;
933#endif
Takashi Iwaie9c364c2009-08-11 17:16:13 +0200934
935 if (preset->setup)
936 preset->setup(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +0100937}
938
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200939/* Enable GPIO mask and set output */
940static struct hda_verb alc_gpio1_init_verbs[] = {
941 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
942 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
943 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
944 { }
945};
946
947static struct hda_verb alc_gpio2_init_verbs[] = {
948 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
949 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
950 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
951 { }
952};
953
Kailang Yangbdd148a2007-05-08 15:19:08 +0200954static struct hda_verb alc_gpio3_init_verbs[] = {
955 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
956 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
957 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
958 { }
959};
960
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200961/*
962 * Fix hardware PLL issue
963 * On some codecs, the analog PLL gating control must be off while
964 * the default value is 1.
965 */
966static void alc_fix_pll(struct hda_codec *codec)
967{
968 struct alc_spec *spec = codec->spec;
969 unsigned int val;
970
971 if (!spec->pll_nid)
972 return;
973 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
974 spec->pll_coef_idx);
975 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
976 AC_VERB_GET_PROC_COEF, 0);
977 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
978 spec->pll_coef_idx);
979 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
980 val & ~(1 << spec->pll_coef_bit));
981}
982
983static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
984 unsigned int coef_idx, unsigned int coef_bit)
985{
986 struct alc_spec *spec = codec->spec;
987 spec->pll_nid = nid;
988 spec->pll_coef_idx = coef_idx;
989 spec->pll_coef_bit = coef_bit;
990 alc_fix_pll(codec);
991}
992
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200993static void alc_automute_pin(struct hda_codec *codec)
Kailang Yangc9b58002007-10-16 14:30:01 +0200994{
995 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +0200996 unsigned int nid = spec->autocfg.hp_pins[0];
997 int i;
Kailang Yangc9b58002007-10-16 14:30:01 +0200998
Takashi Iwaiad87c642009-11-02 14:23:15 +0100999 if (!nid)
1000 return;
Wu Fengguang864f92b2009-11-18 12:38:02 +08001001 spec->jack_present = snd_hda_jack_detect(codec, nid);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001002 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
1003 nid = spec->autocfg.speaker_pins[i];
1004 if (!nid)
1005 break;
1006 snd_hda_codec_write(codec, nid, 0,
1007 AC_VERB_SET_PIN_WIDGET_CONTROL,
1008 spec->jack_present ? 0 : PIN_OUT);
1009 }
Kailang Yangc9b58002007-10-16 14:30:01 +02001010}
1011
Takashi Iwai6c819492009-08-10 18:47:44 +02001012static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
1013 hda_nid_t nid)
1014{
1015 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
1016 int i, nums;
1017
1018 nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
1019 for (i = 0; i < nums; i++)
1020 if (conn[i] == nid)
1021 return i;
1022 return -1;
1023}
1024
Takashi Iwai840b64c2010-07-13 22:49:01 +02001025/* switch the current ADC according to the jack state */
1026static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec)
1027{
1028 struct alc_spec *spec = codec->spec;
1029 unsigned int present;
1030 hda_nid_t new_adc;
1031
1032 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
1033 if (present)
1034 spec->cur_adc_idx = 1;
1035 else
1036 spec->cur_adc_idx = 0;
1037 new_adc = spec->adc_nids[spec->cur_adc_idx];
1038 if (spec->cur_adc && spec->cur_adc != new_adc) {
1039 /* stream is running, let's swap the current ADC */
Takashi Iwaif0cea792010-08-13 11:56:53 +02001040 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
Takashi Iwai840b64c2010-07-13 22:49:01 +02001041 spec->cur_adc = new_adc;
1042 snd_hda_codec_setup_stream(codec, new_adc,
1043 spec->cur_adc_stream_tag, 0,
1044 spec->cur_adc_format);
1045 }
1046}
1047
Kailang Yang7fb0d782008-10-15 11:12:35 +02001048static void alc_mic_automute(struct hda_codec *codec)
1049{
1050 struct alc_spec *spec = codec->spec;
Takashi Iwai6c819492009-08-10 18:47:44 +02001051 struct alc_mic_route *dead, *alive;
1052 unsigned int present, type;
1053 hda_nid_t cap_nid;
Kailang Yang7fb0d782008-10-15 11:12:35 +02001054
Takashi Iwaib59bdf32009-08-11 09:47:30 +02001055 if (!spec->auto_mic)
1056 return;
Takashi Iwai6c819492009-08-10 18:47:44 +02001057 if (!spec->int_mic.pin || !spec->ext_mic.pin)
1058 return;
1059 if (snd_BUG_ON(!spec->adc_nids))
1060 return;
1061
Takashi Iwai840b64c2010-07-13 22:49:01 +02001062 if (spec->dual_adc_switch) {
1063 alc_dual_mic_adc_auto_switch(codec);
1064 return;
1065 }
1066
Takashi Iwai6c819492009-08-10 18:47:44 +02001067 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
1068
Wu Fengguang864f92b2009-11-18 12:38:02 +08001069 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
Takashi Iwai6c819492009-08-10 18:47:44 +02001070 if (present) {
1071 alive = &spec->ext_mic;
1072 dead = &spec->int_mic;
1073 } else {
1074 alive = &spec->int_mic;
1075 dead = &spec->ext_mic;
1076 }
1077
Takashi Iwai6c819492009-08-10 18:47:44 +02001078 type = get_wcaps_type(get_wcaps(codec, cap_nid));
1079 if (type == AC_WID_AUD_MIX) {
1080 /* Matrix-mixer style (e.g. ALC882) */
1081 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1082 alive->mux_idx,
1083 HDA_AMP_MUTE, 0);
1084 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1085 dead->mux_idx,
1086 HDA_AMP_MUTE, HDA_AMP_MUTE);
1087 } else {
1088 /* MUX style (e.g. ALC880) */
1089 snd_hda_codec_write_cache(codec, cap_nid, 0,
1090 AC_VERB_SET_CONNECT_SEL,
1091 alive->mux_idx);
1092 }
1093
1094 /* FIXME: analog mixer */
Kailang Yang7fb0d782008-10-15 11:12:35 +02001095}
1096
Kailang Yangc9b58002007-10-16 14:30:01 +02001097/* unsolicited event for HP jack sensing */
1098static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
1099{
1100 if (codec->vendor_id == 0x10ec0880)
1101 res >>= 28;
1102 else
1103 res >>= 26;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001104 switch (res) {
1105 case ALC880_HP_EVENT:
1106 alc_automute_pin(codec);
1107 break;
1108 case ALC880_MIC_EVENT:
Kailang Yang7fb0d782008-10-15 11:12:35 +02001109 alc_mic_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001110 break;
1111 }
Kailang Yang7fb0d782008-10-15 11:12:35 +02001112}
1113
1114static void alc_inithook(struct hda_codec *codec)
1115{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001116 alc_automute_pin(codec);
Kailang Yang7fb0d782008-10-15 11:12:35 +02001117 alc_mic_automute(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +02001118}
1119
Kailang Yangf9423e72008-05-27 12:32:25 +02001120/* additional initialization for ALC888 variants */
1121static void alc888_coef_init(struct hda_codec *codec)
1122{
1123 unsigned int tmp;
1124
1125 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
1126 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1127 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +01001128 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +02001129 /* alc888S-VC */
1130 snd_hda_codec_read(codec, 0x20, 0,
1131 AC_VERB_SET_PROC_COEF, 0x830);
1132 else
1133 /* alc888-VB */
1134 snd_hda_codec_read(codec, 0x20, 0,
1135 AC_VERB_SET_PROC_COEF, 0x3030);
1136}
1137
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02001138static void alc889_coef_init(struct hda_codec *codec)
1139{
1140 unsigned int tmp;
1141
1142 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1143 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
1144 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
1145 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
1146}
1147
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001148/* turn on/off EAPD control (only if available) */
1149static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
1150{
1151 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
1152 return;
1153 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
1154 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
1155 on ? 2 : 0);
1156}
1157
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001158static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001159{
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001160 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001161
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001162 switch (type) {
1163 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001164 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
1165 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001166 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001167 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
1168 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001169 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001170 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
1171 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001172 case ALC_INIT_DEFAULT:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001173 switch (codec->vendor_id) {
Kailang Yangc9b58002007-10-16 14:30:01 +02001174 case 0x10ec0260:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001175 set_eapd(codec, 0x0f, 1);
1176 set_eapd(codec, 0x10, 1);
Kailang Yangc9b58002007-10-16 14:30:01 +02001177 break;
1178 case 0x10ec0262:
Kailang Yangbdd148a2007-05-08 15:19:08 +02001179 case 0x10ec0267:
1180 case 0x10ec0268:
Kailang Yangc9b58002007-10-16 14:30:01 +02001181 case 0x10ec0269:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001182 case 0x10ec0270:
Takashi Iwaic6e8f2d2009-02-06 12:45:52 +01001183 case 0x10ec0272:
Kailang Yangf9423e72008-05-27 12:32:25 +02001184 case 0x10ec0660:
1185 case 0x10ec0662:
1186 case 0x10ec0663:
Kailang Yangc9b58002007-10-16 14:30:01 +02001187 case 0x10ec0862:
Takashi Iwai20a3a052008-05-23 17:52:53 +02001188 case 0x10ec0889:
Takashi Iwai3fb4a502010-01-19 15:46:37 +01001189 set_eapd(codec, 0x14, 1);
1190 set_eapd(codec, 0x15, 1);
Kailang Yangc9b58002007-10-16 14:30:01 +02001191 break;
Kailang Yangbdd148a2007-05-08 15:19:08 +02001192 }
Kailang Yangc9b58002007-10-16 14:30:01 +02001193 switch (codec->vendor_id) {
1194 case 0x10ec0260:
1195 snd_hda_codec_write(codec, 0x1a, 0,
1196 AC_VERB_SET_COEF_INDEX, 7);
1197 tmp = snd_hda_codec_read(codec, 0x1a, 0,
1198 AC_VERB_GET_PROC_COEF, 0);
1199 snd_hda_codec_write(codec, 0x1a, 0,
1200 AC_VERB_SET_COEF_INDEX, 7);
1201 snd_hda_codec_write(codec, 0x1a, 0,
1202 AC_VERB_SET_PROC_COEF,
1203 tmp | 0x2010);
1204 break;
1205 case 0x10ec0262:
1206 case 0x10ec0880:
1207 case 0x10ec0882:
1208 case 0x10ec0883:
1209 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +01001210 case 0x10ec0887:
Takashi Iwai20a3a052008-05-23 17:52:53 +02001211 case 0x10ec0889:
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02001212 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +02001213 break;
Kailang Yangf9423e72008-05-27 12:32:25 +02001214 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001215 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +02001216 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +01001217#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +02001218 case 0x10ec0267:
1219 case 0x10ec0268:
1220 snd_hda_codec_write(codec, 0x20, 0,
1221 AC_VERB_SET_COEF_INDEX, 7);
1222 tmp = snd_hda_codec_read(codec, 0x20, 0,
1223 AC_VERB_GET_PROC_COEF, 0);
1224 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +02001225 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +02001226 snd_hda_codec_write(codec, 0x20, 0,
1227 AC_VERB_SET_PROC_COEF,
1228 tmp | 0x3000);
1229 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +01001230#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001231 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001232 break;
1233 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001234}
Kailang Yangea1fb292008-08-26 12:58:38 +02001235
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001236static void alc_init_auto_hp(struct hda_codec *codec)
1237{
1238 struct alc_spec *spec = codec->spec;
1239
1240 if (!spec->autocfg.hp_pins[0])
Kailang Yangc9b58002007-10-16 14:30:01 +02001241 return;
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001242
Kailang Yangc9b58002007-10-16 14:30:01 +02001243 if (!spec->autocfg.speaker_pins[0]) {
Takashi Iwai2a2ed0d2009-04-28 13:01:26 +02001244 if (spec->autocfg.line_out_pins[0] &&
1245 spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
Kailang Yangc9b58002007-10-16 14:30:01 +02001246 spec->autocfg.speaker_pins[0] =
Kailang Yang8c427222008-01-10 13:03:59 +01001247 spec->autocfg.line_out_pins[0];
Kailang Yangc9b58002007-10-16 14:30:01 +02001248 else
1249 return;
1250 }
1251
Takashi Iwai2a2ed0d2009-04-28 13:01:26 +02001252 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
1253 spec->autocfg.hp_pins[0]);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001254 snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0,
1255 AC_VERB_SET_UNSOLICITED_ENABLE,
1256 AC_USRSP_EN | ALC880_HP_EVENT);
1257 spec->unsol_event = alc_sku_unsol_event;
1258}
1259
Takashi Iwai6c819492009-08-10 18:47:44 +02001260static void alc_init_auto_mic(struct hda_codec *codec)
1261{
1262 struct alc_spec *spec = codec->spec;
1263 struct auto_pin_cfg *cfg = &spec->autocfg;
1264 hda_nid_t fixed, ext;
1265 int i;
1266
1267 /* there must be only two mic inputs exclusively */
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001268 for (i = 0; i < cfg->num_inputs; i++)
1269 if (cfg->inputs[i].type >= AUTO_PIN_LINE)
Takashi Iwai6c819492009-08-10 18:47:44 +02001270 return;
1271
1272 fixed = ext = 0;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02001273 for (i = 0; i < cfg->num_inputs; i++) {
1274 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai6c819492009-08-10 18:47:44 +02001275 unsigned int defcfg;
Takashi Iwai6c819492009-08-10 18:47:44 +02001276 defcfg = snd_hda_codec_get_pincfg(codec, nid);
1277 switch (get_defcfg_connect(defcfg)) {
1278 case AC_JACK_PORT_FIXED:
1279 if (fixed)
1280 return; /* already occupied */
1281 fixed = nid;
1282 break;
1283 case AC_JACK_PORT_COMPLEX:
1284 if (ext)
1285 return; /* already occupied */
1286 ext = nid;
1287 break;
1288 default:
1289 return; /* invalid entry */
1290 }
1291 }
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01001292 if (!ext || !fixed)
1293 return;
Takashi Iwai6c819492009-08-10 18:47:44 +02001294 if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
1295 return; /* no unsol support */
1296 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
1297 ext, fixed);
1298 spec->ext_mic.pin = ext;
1299 spec->int_mic.pin = fixed;
1300 spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1301 spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1302 spec->auto_mic = 1;
1303 snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
1304 AC_VERB_SET_UNSOLICITED_ENABLE,
1305 AC_USRSP_EN | ALC880_MIC_EVENT);
1306 spec->unsol_event = alc_sku_unsol_event;
1307}
1308
Kailang Yangda00c242010-03-19 11:23:45 +01001309static int alc_auto_parse_customize_define(struct hda_codec *codec)
1310{
1311 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +01001312 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +01001313 struct alc_spec *spec = codec->spec;
1314
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001315 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1316
Kailang Yangda00c242010-03-19 11:23:45 +01001317 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +02001318 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +01001319 goto do_sku;
1320
1321 nid = 0x1d;
1322 if (codec->vendor_id == 0x10ec0260)
1323 nid = 0x17;
1324 ass = snd_hda_codec_get_pincfg(codec, nid);
1325
1326 if (!(ass & 1)) {
1327 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1328 codec->chip_name, ass);
1329 return -1;
1330 }
1331
1332 /* check sum */
1333 tmp = 0;
1334 for (i = 1; i < 16; i++) {
1335 if ((ass >> i) & 1)
1336 tmp++;
1337 }
1338 if (((ass >> 16) & 0xf) != tmp)
1339 return -1;
1340
1341 spec->cdefine.port_connectivity = ass >> 30;
1342 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1343 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1344 spec->cdefine.customization = ass >> 8;
1345do_sku:
1346 spec->cdefine.sku_cfg = ass;
1347 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1348 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1349 spec->cdefine.swap = (ass & 0x2) >> 1;
1350 spec->cdefine.override = ass & 0x1;
1351
1352 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1353 nid, spec->cdefine.sku_cfg);
1354 snd_printd("SKU: port_connectivity=0x%x\n",
1355 spec->cdefine.port_connectivity);
1356 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1357 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1358 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1359 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1360 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1361 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1362 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1363
1364 return 0;
1365}
1366
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001367/* check subsystem ID and set up device-specific initialization;
1368 * return 1 if initialized, 0 if invalid SSID
1369 */
1370/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
1371 * 31 ~ 16 : Manufacture ID
1372 * 15 ~ 8 : SKU ID
1373 * 7 ~ 0 : Assembly ID
1374 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
1375 */
1376static int alc_subsystem_id(struct hda_codec *codec,
1377 hda_nid_t porta, hda_nid_t porte,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001378 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001379{
1380 unsigned int ass, tmp, i;
1381 unsigned nid;
1382 struct alc_spec *spec = codec->spec;
1383
1384 ass = codec->subsystem_id & 0xffff;
1385 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1386 goto do_sku;
1387
1388 /* invalid SSID, check the special NID pin defcfg instead */
1389 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04001390 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001391 * 29~21 : reserve
1392 * 20 : PCBEEP input
1393 * 19~16 : Check sum (15:1)
1394 * 15~1 : Custom
1395 * 0 : override
1396 */
1397 nid = 0x1d;
1398 if (codec->vendor_id == 0x10ec0260)
1399 nid = 0x17;
1400 ass = snd_hda_codec_get_pincfg(codec, nid);
1401 snd_printd("realtek: No valid SSID, "
1402 "checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +02001403 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +01001404 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001405 return 0;
1406 if ((ass >> 30) != 1) /* no physical connection */
1407 return 0;
1408
1409 /* check sum */
1410 tmp = 0;
1411 for (i = 1; i < 16; i++) {
1412 if ((ass >> i) & 1)
1413 tmp++;
1414 }
1415 if (((ass >> 16) & 0xf) != tmp)
1416 return 0;
1417do_sku:
1418 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
1419 ass & 0xffff, codec->vendor_id);
1420 /*
1421 * 0 : override
1422 * 1 : Swap Jack
1423 * 2 : 0 --> Desktop, 1 --> Laptop
1424 * 3~5 : External Amplifier control
1425 * 7~6 : Reserved
1426 */
1427 tmp = (ass & 0x38) >> 3; /* external Amp control */
1428 switch (tmp) {
1429 case 1:
1430 spec->init_amp = ALC_INIT_GPIO1;
1431 break;
1432 case 3:
1433 spec->init_amp = ALC_INIT_GPIO2;
1434 break;
1435 case 7:
1436 spec->init_amp = ALC_INIT_GPIO3;
1437 break;
1438 case 5:
1439 spec->init_amp = ALC_INIT_DEFAULT;
1440 break;
1441 }
1442
1443 /* is laptop or Desktop and enable the function "Mute internal speaker
1444 * when the external headphone out jack is plugged"
1445 */
1446 if (!(ass & 0x8000))
1447 return 1;
1448 /*
1449 * 10~8 : Jack location
1450 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
1451 * 14~13: Resvered
1452 * 15 : 1 --> enable the function "Mute internal speaker
1453 * when the external headphone out jack is plugged"
1454 */
Kailang Yangc9b58002007-10-16 14:30:01 +02001455 if (!spec->autocfg.hp_pins[0]) {
Takashi Iwai01d48252009-10-06 13:21:54 +02001456 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001457 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1458 if (tmp == 0)
Takashi Iwai01d48252009-10-06 13:21:54 +02001459 nid = porta;
Kailang Yangc9b58002007-10-16 14:30:01 +02001460 else if (tmp == 1)
Takashi Iwai01d48252009-10-06 13:21:54 +02001461 nid = porte;
Kailang Yangc9b58002007-10-16 14:30:01 +02001462 else if (tmp == 2)
Takashi Iwai01d48252009-10-06 13:21:54 +02001463 nid = portd;
Kailang Yang6227cdc2010-02-25 08:36:52 +01001464 else if (tmp == 3)
1465 nid = porti;
Kailang Yangc9b58002007-10-16 14:30:01 +02001466 else
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001467 return 1;
Takashi Iwai01d48252009-10-06 13:21:54 +02001468 for (i = 0; i < spec->autocfg.line_outs; i++)
1469 if (spec->autocfg.line_out_pins[i] == nid)
1470 return 1;
1471 spec->autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +02001472 }
1473
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001474 alc_init_auto_hp(codec);
Takashi Iwai6c819492009-08-10 18:47:44 +02001475 alc_init_auto_mic(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001476 return 1;
1477}
Kailang Yangea1fb292008-08-26 12:58:38 +02001478
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001479static void alc_ssid_check(struct hda_codec *codec,
Kailang Yang6227cdc2010-02-25 08:36:52 +01001480 hda_nid_t porta, hda_nid_t porte,
1481 hda_nid_t portd, hda_nid_t porti)
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001482{
Kailang Yang6227cdc2010-02-25 08:36:52 +01001483 if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001484 struct alc_spec *spec = codec->spec;
1485 snd_printd("realtek: "
1486 "Enable default setup for auto mode as fallback\n");
1487 spec->init_amp = ALC_INIT_DEFAULT;
1488 alc_init_auto_hp(codec);
Takashi Iwai6c819492009-08-10 18:47:44 +02001489 alc_init_auto_mic(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02001490 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +02001491}
1492
Takashi Iwai41e41f12005-06-08 14:48:49 +02001493/*
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001494 * Fix-up pin default configurations and add default verbs
Takashi Iwaif95474e2007-07-10 00:47:43 +02001495 */
1496
1497struct alc_pincfg {
1498 hda_nid_t nid;
1499 u32 val;
1500};
1501
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001502struct alc_fixup {
1503 const struct alc_pincfg *pins;
1504 const struct hda_verb *verbs;
1505};
1506
1507static void alc_pick_fixup(struct hda_codec *codec,
Takashi Iwaif95474e2007-07-10 00:47:43 +02001508 const struct snd_pci_quirk *quirk,
Takashi Iwai7fa90e82010-04-12 08:49:00 +02001509 const struct alc_fixup *fix,
1510 int pre_init)
Takashi Iwaif95474e2007-07-10 00:47:43 +02001511{
1512 const struct alc_pincfg *cfg;
1513
1514 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1515 if (!quirk)
1516 return;
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001517 fix += quirk->value;
1518 cfg = fix->pins;
Takashi Iwai7fa90e82010-04-12 08:49:00 +02001519 if (pre_init && cfg) {
1520#ifdef CONFIG_SND_DEBUG_VERBOSE
1521 snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n",
1522 codec->chip_name, quirk->name);
1523#endif
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001524 for (; cfg->nid; cfg++)
1525 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
1526 }
Takashi Iwai7fa90e82010-04-12 08:49:00 +02001527 if (!pre_init && fix->verbs) {
1528#ifdef CONFIG_SND_DEBUG_VERBOSE
1529 snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-verbs for %s\n",
1530 codec->chip_name, quirk->name);
1531#endif
Takashi Iwaif8f25ba2009-10-06 08:31:29 +02001532 add_verb(codec->spec, fix->verbs);
Takashi Iwai7fa90e82010-04-12 08:49:00 +02001533 }
Takashi Iwaif95474e2007-07-10 00:47:43 +02001534}
1535
Kailang Yang274693f2009-12-03 10:07:50 +01001536static int alc_read_coef_idx(struct hda_codec *codec,
1537 unsigned int coef_idx)
1538{
1539 unsigned int val;
1540 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1541 coef_idx);
1542 val = snd_hda_codec_read(codec, 0x20, 0,
1543 AC_VERB_GET_PROC_COEF, 0);
1544 return val;
1545}
1546
Takashi Iwai757899a2010-07-30 10:48:14 +02001547/* set right pin controls for digital I/O */
1548static void alc_auto_init_digital(struct hda_codec *codec)
1549{
1550 struct alc_spec *spec = codec->spec;
1551 int i;
1552 hda_nid_t pin;
1553
1554 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1555 pin = spec->autocfg.dig_out_pins[i];
1556 if (pin) {
1557 snd_hda_codec_write(codec, pin, 0,
1558 AC_VERB_SET_PIN_WIDGET_CONTROL,
1559 PIN_OUT);
1560 }
1561 }
1562 pin = spec->autocfg.dig_in_pin;
1563 if (pin)
1564 snd_hda_codec_write(codec, pin, 0,
1565 AC_VERB_SET_PIN_WIDGET_CONTROL,
1566 PIN_IN);
1567}
1568
1569/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1570static void alc_auto_parse_digital(struct hda_codec *codec)
1571{
1572 struct alc_spec *spec = codec->spec;
1573 int i, err;
1574 hda_nid_t dig_nid;
1575
1576 /* support multiple SPDIFs; the secondary is set up as a slave */
1577 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1578 err = snd_hda_get_connections(codec,
1579 spec->autocfg.dig_out_pins[i],
1580 &dig_nid, 1);
1581 if (err < 0)
1582 continue;
1583 if (!i) {
1584 spec->multiout.dig_out_nid = dig_nid;
1585 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1586 } else {
1587 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1588 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1589 break;
1590 spec->slave_dig_outs[i - 1] = dig_nid;
1591 }
1592 }
1593
1594 if (spec->autocfg.dig_in_pin) {
1595 hda_nid_t dig_nid;
1596 err = snd_hda_get_connections(codec,
1597 spec->autocfg.dig_in_pin,
1598 &dig_nid, 1);
1599 if (err > 0)
1600 spec->dig_in_nid = dig_nid;
1601 }
1602}
1603
Takashi Iwaif95474e2007-07-10 00:47:43 +02001604/*
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001605 * ALC888
1606 */
1607
1608/*
1609 * 2ch mode
1610 */
1611static struct hda_verb alc888_4ST_ch2_intel_init[] = {
1612/* Mic-in jack as mic in */
1613 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1614 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1615/* Line-in jack as Line in */
1616 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1617 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1618/* Line-Out as Front */
1619 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1620 { } /* end */
1621};
1622
1623/*
1624 * 4ch mode
1625 */
1626static struct hda_verb alc888_4ST_ch4_intel_init[] = {
1627/* Mic-in jack as mic in */
1628 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1629 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1630/* Line-in jack as Surround */
1631 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1632 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1633/* Line-Out as Front */
1634 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
1635 { } /* end */
1636};
1637
1638/*
1639 * 6ch mode
1640 */
1641static struct hda_verb alc888_4ST_ch6_intel_init[] = {
1642/* Mic-in jack as CLFE */
1643 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1644 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1645/* Line-in jack as Surround */
1646 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1647 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1648/* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
1649 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1650 { } /* end */
1651};
1652
1653/*
1654 * 8ch mode
1655 */
1656static struct hda_verb alc888_4ST_ch8_intel_init[] = {
1657/* Mic-in jack as CLFE */
1658 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1659 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1660/* Line-in jack as Surround */
1661 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1662 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1663/* Line-Out as Side */
1664 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1665 { } /* end */
1666};
1667
1668static struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
1669 { 2, alc888_4ST_ch2_intel_init },
1670 { 4, alc888_4ST_ch4_intel_init },
1671 { 6, alc888_4ST_ch6_intel_init },
1672 { 8, alc888_4ST_ch8_intel_init },
1673};
1674
1675/*
1676 * ALC888 Fujitsu Siemens Amillo xa3530
1677 */
1678
1679static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
1680/* Front Mic: set to PIN_IN (empty by default) */
1681 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1682/* Connect Internal HP to Front */
1683 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1684 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1685 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1686/* Connect Bass HP to Front */
1687 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1688 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1689 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1690/* Connect Line-Out side jack (SPDIF) to Side */
1691 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1692 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1693 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1694/* Connect Mic jack to CLFE */
1695 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1696 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1697 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
1698/* Connect Line-in jack to Surround */
1699 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1700 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1701 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
1702/* Connect HP out jack to Front */
1703 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1704 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1705 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1706/* Enable unsolicited event for HP jack and Line-out jack */
1707 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1708 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1709 {}
1710};
1711
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001712static void alc_automute_amp(struct hda_codec *codec)
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001713{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001714 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +08001715 unsigned int mute;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001716 hda_nid_t nid;
1717 int i;
1718
1719 spec->jack_present = 0;
1720 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
1721 nid = spec->autocfg.hp_pins[i];
1722 if (!nid)
1723 break;
Wu Fengguang864f92b2009-11-18 12:38:02 +08001724 if (snd_hda_jack_detect(codec, nid)) {
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001725 spec->jack_present = 1;
1726 break;
1727 }
1728 }
1729
1730 mute = spec->jack_present ? HDA_AMP_MUTE : 0;
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001731 /* Toggle internal speakers muting */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001732 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
1733 nid = spec->autocfg.speaker_pins[i];
1734 if (!nid)
1735 break;
1736 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1737 HDA_AMP_MUTE, mute);
1738 }
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001739}
1740
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001741static void alc_automute_amp_unsol_event(struct hda_codec *codec,
1742 unsigned int res)
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001743{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001744 if (codec->vendor_id == 0x10ec0880)
1745 res >>= 28;
1746 else
1747 res >>= 26;
1748 if (res == ALC880_HP_EVENT)
1749 alc_automute_amp(codec);
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001750}
1751
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001752static void alc889_automute_setup(struct hda_codec *codec)
Wu Fengguang6732bd02009-07-30 09:19:14 +02001753{
1754 struct alc_spec *spec = codec->spec;
1755
1756 spec->autocfg.hp_pins[0] = 0x15;
1757 spec->autocfg.speaker_pins[0] = 0x14;
1758 spec->autocfg.speaker_pins[1] = 0x16;
1759 spec->autocfg.speaker_pins[2] = 0x17;
1760 spec->autocfg.speaker_pins[3] = 0x19;
1761 spec->autocfg.speaker_pins[4] = 0x1a;
Wu Fengguang6732bd02009-07-30 09:19:14 +02001762}
1763
1764static void alc889_intel_init_hook(struct hda_codec *codec)
1765{
1766 alc889_coef_init(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001767 alc_automute_amp(codec);
Wu Fengguang6732bd02009-07-30 09:19:14 +02001768}
1769
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001770static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001771{
1772 struct alc_spec *spec = codec->spec;
1773
1774 spec->autocfg.hp_pins[0] = 0x17; /* line-out */
1775 spec->autocfg.hp_pins[1] = 0x1b; /* hp */
1776 spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
1777 spec->autocfg.speaker_pins[1] = 0x15; /* bass */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02001778}
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001779
1780/*
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001781 * ALC888 Acer Aspire 4930G model
1782 */
1783
1784static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
1785/* Front Mic: set to PIN_IN (empty by default) */
1786 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1787/* Unselect Front Mic by default in input mixer 3 */
1788 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001789/* Enable unsolicited event for HP jack */
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001790 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1791/* Connect Internal HP to front */
1792 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1793 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1794 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1795/* Connect HP out to front */
1796 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1797 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1798 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1799 { }
1800};
1801
Hector Martin3b315d72009-06-02 10:54:19 +02001802/*
Tony Vroond2fd4b02009-06-21 00:40:10 +01001803 * ALC888 Acer Aspire 6530G model
1804 */
1805
1806static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
Tony Vroond1284182010-04-05 16:30:43 +01001807/* Route to built-in subwoofer as well as speakers */
1808 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1809 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1810 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1811 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001812/* Bias voltage on for external mic port */
1813 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
Emilio López320d5922009-06-25 08:18:44 +02001814/* Front Mic: set to PIN_IN (empty by default) */
1815 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1816/* Unselect Front Mic by default in input mixer 3 */
1817 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001818/* Enable unsolicited event for HP jack */
1819 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1820/* Enable speaker output */
1821 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1822 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Tony Vroond1284182010-04-05 16:30:43 +01001823 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001824/* Enable headphone output */
1825 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
1826 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1827 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
Tony Vroond1284182010-04-05 16:30:43 +01001828 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
Tony Vroond2fd4b02009-06-21 00:40:10 +01001829 { }
1830};
1831
1832/*
Hector Martin018df412009-06-04 00:13:40 +02001833 * ALC889 Acer Aspire 8930G model
Hector Martin3b315d72009-06-02 10:54:19 +02001834 */
1835
Hector Martin018df412009-06-04 00:13:40 +02001836static struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
Hector Martin3b315d72009-06-02 10:54:19 +02001837/* Front Mic: set to PIN_IN (empty by default) */
1838 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1839/* Unselect Front Mic by default in input mixer 3 */
1840 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
1841/* Enable unsolicited event for HP jack */
1842 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
1843/* Connect Internal Front to Front */
1844 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1845 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1846 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1847/* Connect Internal Rear to Rear */
1848 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1849 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1850 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
1851/* Connect Internal CLFE to CLFE */
1852 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1853 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1854 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
1855/* Connect HP out to Front */
Hector Martin018df412009-06-04 00:13:40 +02001856 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
Hector Martin3b315d72009-06-02 10:54:19 +02001857 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1858 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1859/* Enable all DACs */
1860/* DAC DISABLE/MUTE 1? */
1861/* setting bits 1-5 disables DAC nids 0x02-0x06 apparently. Init=0x38 */
1862 {0x20, AC_VERB_SET_COEF_INDEX, 0x03},
1863 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
1864/* DAC DISABLE/MUTE 2? */
1865/* some bit here disables the other DACs. Init=0x4900 */
1866 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
1867 {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
Hector Martin018df412009-06-04 00:13:40 +02001868/* DMIC fix
1869 * This laptop has a stereo digital microphone. The mics are only 1cm apart
1870 * which makes the stereo useless. However, either the mic or the ALC889
1871 * makes the signal become a difference/sum signal instead of standard
1872 * stereo, which is annoying. So instead we flip this bit which makes the
1873 * codec replicate the sum signal to both channels, turning it into a
1874 * normal mono mic.
1875 */
1876/* DMIC_CONTROL? Init value = 0x0001 */
1877 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
1878 {0x20, AC_VERB_SET_PROC_COEF, 0x0003},
Hector Martin3b315d72009-06-02 10:54:19 +02001879 { }
1880};
1881
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001882static struct hda_input_mux alc888_2_capture_sources[2] = {
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001883 /* Front mic only available on one ADC */
1884 {
1885 .num_items = 4,
1886 .items = {
1887 { "Mic", 0x0 },
1888 { "Line", 0x2 },
1889 { "CD", 0x4 },
1890 { "Front Mic", 0xb },
1891 },
1892 },
1893 {
1894 .num_items = 3,
1895 .items = {
1896 { "Mic", 0x0 },
1897 { "Line", 0x2 },
1898 { "CD", 0x4 },
1899 },
1900 }
1901};
1902
Tony Vroond2fd4b02009-06-21 00:40:10 +01001903static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
1904 /* Interal mic only available on one ADC */
1905 {
Tony Vroon684a8842009-06-26 09:27:50 +01001906 .num_items = 5,
Tony Vroond2fd4b02009-06-21 00:40:10 +01001907 .items = {
1908 { "Ext Mic", 0x0 },
Tony Vroon684a8842009-06-26 09:27:50 +01001909 { "Line In", 0x2 },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001910 { "CD", 0x4 },
Tony Vroon684a8842009-06-26 09:27:50 +01001911 { "Input Mix", 0xa },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001912 { "Int Mic", 0xb },
1913 },
1914 },
1915 {
Tony Vroon684a8842009-06-26 09:27:50 +01001916 .num_items = 4,
Tony Vroond2fd4b02009-06-21 00:40:10 +01001917 .items = {
1918 { "Ext Mic", 0x0 },
Tony Vroon684a8842009-06-26 09:27:50 +01001919 { "Line In", 0x2 },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001920 { "CD", 0x4 },
Tony Vroon684a8842009-06-26 09:27:50 +01001921 { "Input Mix", 0xa },
Tony Vroond2fd4b02009-06-21 00:40:10 +01001922 },
1923 }
1924};
1925
Hector Martin018df412009-06-04 00:13:40 +02001926static struct hda_input_mux alc889_capture_sources[3] = {
1927 /* Digital mic only available on first "ADC" */
1928 {
1929 .num_items = 5,
1930 .items = {
1931 { "Mic", 0x0 },
1932 { "Line", 0x2 },
1933 { "CD", 0x4 },
1934 { "Front Mic", 0xb },
1935 { "Input Mix", 0xa },
1936 },
1937 },
1938 {
1939 .num_items = 4,
1940 .items = {
1941 { "Mic", 0x0 },
1942 { "Line", 0x2 },
1943 { "CD", 0x4 },
1944 { "Input Mix", 0xa },
1945 },
1946 },
1947 {
1948 .num_items = 4,
1949 .items = {
1950 { "Mic", 0x0 },
1951 { "Line", 0x2 },
1952 { "CD", 0x4 },
1953 { "Input Mix", 0xa },
1954 },
1955 }
1956};
1957
Vincent Petryef8ef5f2008-11-23 11:31:41 +08001958static struct snd_kcontrol_new alc888_base_mixer[] = {
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001959 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1960 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1961 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1962 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1963 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
1964 HDA_OUTPUT),
1965 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1966 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1967 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1968 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1969 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1970 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1971 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1972 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1973 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1974 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1975 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
1976 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08001977 { } /* end */
1978};
1979
Hector Martin556eea92009-12-20 22:51:23 +01001980static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
1981 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1982 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1983 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1984 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1985 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
1986 HDA_OUTPUT),
1987 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1988 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1989 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1990 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1991 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1992 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1993 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
1994 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1995 { } /* end */
1996};
1997
1998
Takashi Iwai4f5d17062009-08-11 18:17:46 +02001999static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08002000{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002001 struct alc_spec *spec = codec->spec;
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08002002
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02002003 spec->autocfg.hp_pins[0] = 0x15;
2004 spec->autocfg.speaker_pins[0] = 0x14;
Łukasz Wojniłowicz7cef4cf2009-11-20 12:14:35 +01002005 spec->autocfg.speaker_pins[1] = 0x16;
2006 spec->autocfg.speaker_pins[2] = 0x17;
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08002007}
2008
Takashi Iwai4f5d17062009-08-11 18:17:46 +02002009static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
Emilio López320d5922009-06-25 08:18:44 +02002010{
2011 struct alc_spec *spec = codec->spec;
2012
2013 spec->autocfg.hp_pins[0] = 0x15;
2014 spec->autocfg.speaker_pins[0] = 0x14;
2015 spec->autocfg.speaker_pins[1] = 0x16;
2016 spec->autocfg.speaker_pins[2] = 0x17;
Emilio López320d5922009-06-25 08:18:44 +02002017}
2018
Takashi Iwai4f5d17062009-08-11 18:17:46 +02002019static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
Hector Martin3b315d72009-06-02 10:54:19 +02002020{
2021 struct alc_spec *spec = codec->spec;
2022
2023 spec->autocfg.hp_pins[0] = 0x15;
2024 spec->autocfg.speaker_pins[0] = 0x14;
2025 spec->autocfg.speaker_pins[1] = 0x16;
2026 spec->autocfg.speaker_pins[2] = 0x1b;
Hector Martin3b315d72009-06-02 10:54:19 +02002027}
2028
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08002029/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002030 * ALC880 3-stack model
2031 *
2032 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002033 * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
2034 * F-Mic = 0x1b, HP = 0x19
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 */
2036
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002037static hda_nid_t alc880_dac_nids[4] = {
2038 /* front, rear, clfe, rear_surr */
2039 0x02, 0x05, 0x04, 0x03
2040};
2041
2042static hda_nid_t alc880_adc_nids[3] = {
2043 /* ADC0-2 */
2044 0x07, 0x08, 0x09,
2045};
2046
2047/* The datasheet says the node 0x07 is connected from inputs,
2048 * but it shows zero connection in the real implementation on some devices.
Kailang Yangdf694da2005-12-05 19:42:22 +01002049 * Note: this is a 915GAV bug, fixed on 915GLV
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002051static hda_nid_t alc880_adc_nids_alt[2] = {
2052 /* ADC1-2 */
2053 0x08, 0x09,
2054};
2055
2056#define ALC880_DIGOUT_NID 0x06
2057#define ALC880_DIGIN_NID 0x0a
2058
2059static struct hda_input_mux alc880_capture_source = {
2060 .num_items = 4,
2061 .items = {
2062 { "Mic", 0x0 },
2063 { "Front Mic", 0x3 },
2064 { "Line", 0x2 },
2065 { "CD", 0x4 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002067};
2068
2069/* channel source setting (2/6 channel selection for 3-stack) */
2070/* 2ch mode */
2071static struct hda_verb alc880_threestack_ch2_init[] = {
2072 /* set line-in to input, mute it */
2073 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2074 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2075 /* set mic-in to input vref 80%, mute it */
2076 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2077 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 { } /* end */
2079};
2080
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002081/* 6ch mode */
2082static struct hda_verb alc880_threestack_ch6_init[] = {
2083 /* set line-in to output, unmute it */
2084 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2085 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2086 /* set mic-in to output, unmute it */
2087 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2088 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2089 { } /* end */
2090};
2091
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002092static struct hda_channel_mode alc880_threestack_modes[2] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002093 { 2, alc880_threestack_ch2_init },
2094 { 6, alc880_threestack_ch6_init },
2095};
2096
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002097static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02002098 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002099 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02002100 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002101 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02002102 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2103 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002104 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2105 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2107 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2108 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2109 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2110 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2111 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2112 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
2113 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002115 {
2116 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2117 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01002118 .info = alc_ch_mode_info,
2119 .get = alc_ch_mode_get,
2120 .put = alc_ch_mode_put,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002121 },
2122 { } /* end */
2123};
2124
2125/* capture mixer elements */
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002126static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
2127 struct snd_ctl_elem_info *uinfo)
2128{
2129 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2130 struct alc_spec *spec = codec->spec;
2131 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002132
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002133 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002134 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
2135 HDA_INPUT);
2136 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002137 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002138 return err;
2139}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002141static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
2142 unsigned int size, unsigned int __user *tlv)
2143{
2144 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2145 struct alc_spec *spec = codec->spec;
2146 int err;
2147
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002148 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002149 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
2150 HDA_INPUT);
2151 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002152 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002153 return err;
2154}
2155
2156typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
2157 struct snd_ctl_elem_value *ucontrol);
2158
2159static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
2160 struct snd_ctl_elem_value *ucontrol,
2161 getput_call_t func)
2162{
2163 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2164 struct alc_spec *spec = codec->spec;
2165 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2166 int err;
2167
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002168 mutex_lock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002169 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx],
2170 3, 0, HDA_INPUT);
2171 err = func(kcontrol, ucontrol);
Wu Fengguang5a9e02e2009-01-09 16:45:24 +08002172 mutex_unlock(&codec->control_mutex);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002173 return err;
2174}
2175
2176static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
2177 struct snd_ctl_elem_value *ucontrol)
2178{
2179 return alc_cap_getput_caller(kcontrol, ucontrol,
2180 snd_hda_mixer_amp_volume_get);
2181}
2182
2183static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
2184 struct snd_ctl_elem_value *ucontrol)
2185{
2186 return alc_cap_getput_caller(kcontrol, ucontrol,
2187 snd_hda_mixer_amp_volume_put);
2188}
2189
2190/* capture mixer elements */
2191#define alc_cap_sw_info snd_ctl_boolean_stereo_info
2192
2193static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
2194 struct snd_ctl_elem_value *ucontrol)
2195{
2196 return alc_cap_getput_caller(kcontrol, ucontrol,
2197 snd_hda_mixer_amp_switch_get);
2198}
2199
2200static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
2201 struct snd_ctl_elem_value *ucontrol)
2202{
2203 return alc_cap_getput_caller(kcontrol, ucontrol,
2204 snd_hda_mixer_amp_switch_put);
2205}
2206
Takashi Iwaia23b6882009-03-23 15:21:36 +01002207#define _DEFINE_CAPMIX(num) \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002208 { \
2209 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2210 .name = "Capture Switch", \
2211 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
2212 .count = num, \
2213 .info = alc_cap_sw_info, \
2214 .get = alc_cap_sw_get, \
2215 .put = alc_cap_sw_put, \
2216 }, \
2217 { \
2218 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2219 .name = "Capture Volume", \
2220 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2221 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
2222 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
2223 .count = num, \
2224 .info = alc_cap_vol_info, \
2225 .get = alc_cap_vol_get, \
2226 .put = alc_cap_vol_put, \
2227 .tlv = { .c = alc_cap_vol_tlv }, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01002228 }
2229
2230#define _DEFINE_CAPSRC(num) \
Takashi Iwai3c3e9892008-10-31 17:48:56 +01002231 { \
2232 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2233 /* .name = "Capture Source", */ \
2234 .name = "Input Source", \
2235 .count = num, \
2236 .info = alc_mux_enum_info, \
2237 .get = alc_mux_enum_get, \
2238 .put = alc_mux_enum_put, \
Takashi Iwaia23b6882009-03-23 15:21:36 +01002239 }
2240
2241#define DEFINE_CAPMIX(num) \
2242static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
2243 _DEFINE_CAPMIX(num), \
2244 _DEFINE_CAPSRC(num), \
2245 { } /* end */ \
2246}
2247
2248#define DEFINE_CAPMIX_NOSRC(num) \
2249static struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
2250 _DEFINE_CAPMIX(num), \
2251 { } /* end */ \
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002252}
2253
2254/* up to three ADCs */
2255DEFINE_CAPMIX(1);
2256DEFINE_CAPMIX(2);
2257DEFINE_CAPMIX(3);
Takashi Iwaia23b6882009-03-23 15:21:36 +01002258DEFINE_CAPMIX_NOSRC(1);
2259DEFINE_CAPMIX_NOSRC(2);
2260DEFINE_CAPMIX_NOSRC(3);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002261
2262/*
2263 * ALC880 5-stack model
2264 *
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002265 * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
2266 * Side = 0x02 (0xd)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002267 * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
2268 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
2269 */
2270
2271/* additional mixers to alc880_three_stack_mixer */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002272static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002273 HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002274 HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 { } /* end */
2276};
2277
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002278/* channel source setting (6/8 channel selection for 5-stack) */
2279/* 6ch mode */
2280static struct hda_verb alc880_fivestack_ch6_init[] = {
2281 /* set line-in to input, mute it */
2282 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2283 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002284 { } /* end */
2285};
2286
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002287/* 8ch mode */
2288static struct hda_verb alc880_fivestack_ch8_init[] = {
2289 /* set line-in to output, unmute it */
2290 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2291 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2292 { } /* end */
2293};
2294
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002295static struct hda_channel_mode alc880_fivestack_modes[2] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002296 { 6, alc880_fivestack_ch6_init },
2297 { 8, alc880_fivestack_ch8_init },
2298};
2299
2300
2301/*
2302 * ALC880 6-stack model
2303 *
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002304 * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
2305 * Side = 0x05 (0x0f)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002306 * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
2307 * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
2308 */
2309
2310static hda_nid_t alc880_6st_dac_nids[4] = {
2311 /* front, rear, clfe, rear_surr */
2312 0x02, 0x03, 0x04, 0x05
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02002313};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002314
2315static struct hda_input_mux alc880_6stack_capture_source = {
2316 .num_items = 4,
2317 .items = {
2318 { "Mic", 0x0 },
2319 { "Front Mic", 0x1 },
2320 { "Line", 0x2 },
2321 { "CD", 0x4 },
2322 },
2323};
2324
2325/* fixed 8-channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002326static struct hda_channel_mode alc880_sixstack_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002327 { 8, NULL },
2328};
2329
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002330static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002331 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002332 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002333 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002334 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002335 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2336 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002337 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2338 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002339 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002340 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002341 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2342 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2343 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2344 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2345 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2346 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2347 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2348 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002349 {
2350 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2351 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01002352 .info = alc_ch_mode_info,
2353 .get = alc_ch_mode_get,
2354 .put = alc_ch_mode_put,
Takashi Iwai16ded522005-06-10 19:58:24 +02002355 },
2356 { } /* end */
2357};
2358
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002359
2360/*
2361 * ALC880 W810 model
2362 *
2363 * W810 has rear IO for:
2364 * Front (DAC 02)
2365 * Surround (DAC 03)
2366 * Center/LFE (DAC 04)
2367 * Digital out (06)
2368 *
2369 * The system also has a pair of internal speakers, and a headphone jack.
2370 * These are both connected to Line2 on the codec, hence to DAC 02.
Kailang Yangea1fb292008-08-26 12:58:38 +02002371 *
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002372 * There is a variable resistor to control the speaker or headphone
2373 * volume. This is a hardware-only device without a software API.
2374 *
2375 * Plugging headphones in will disable the internal speakers. This is
2376 * implemented in hardware, not via the driver using jack sense. In
2377 * a similar fashion, plugging into the rear socket marked "front" will
2378 * disable both the speakers and headphones.
2379 *
2380 * For input, there's a microphone jack, and an "audio in" jack.
2381 * These may not do anything useful with this driver yet, because I
2382 * haven't setup any initialization verbs for these yet...
2383 */
2384
2385static hda_nid_t alc880_w810_dac_nids[3] = {
2386 /* front, rear/surround, clfe */
2387 0x02, 0x03, 0x04
2388};
2389
2390/* fixed 6 channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002391static struct hda_channel_mode alc880_w810_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002392 { 6, NULL }
2393};
2394
2395/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002396static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002397 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002398 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002399 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002400 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002401 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2402 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002403 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2404 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002405 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2406 { } /* end */
2407};
2408
2409
2410/*
2411 * Z710V model
2412 *
2413 * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002414 * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
2415 * Line = 0x1a
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002416 */
2417
2418static hda_nid_t alc880_z71v_dac_nids[1] = {
2419 0x02
2420};
2421#define ALC880_Z71V_HP_DAC 0x03
2422
2423/* fixed 2 channels */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01002424static struct hda_channel_mode alc880_2_jack_modes[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002425 { 2, NULL }
2426};
2427
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002428static struct snd_kcontrol_new alc880_z71v_mixer[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002429 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002430 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002431 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002432 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002433 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2434 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2435 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2436 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2437 { } /* end */
2438};
2439
2440
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002441/*
2442 * ALC880 F1734 model
2443 *
2444 * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
2445 * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
2446 */
2447
2448static hda_nid_t alc880_f1734_dac_nids[1] = {
2449 0x03
2450};
2451#define ALC880_F1734_HP_DAC 0x02
2452
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002453static struct snd_kcontrol_new alc880_f1734_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002454 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002455 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01002456 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2457 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002458 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2459 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Takashi Iwai937b4162008-02-11 14:52:36 +01002460 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2461 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002462 { } /* end */
2463};
2464
Takashi Iwai937b4162008-02-11 14:52:36 +01002465static struct hda_input_mux alc880_f1734_capture_source = {
2466 .num_items = 2,
2467 .items = {
2468 { "Mic", 0x1 },
2469 { "CD", 0x4 },
2470 },
2471};
2472
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002473
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002474/*
2475 * ALC880 ASUS model
2476 *
2477 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
2478 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
2479 * Mic = 0x18, Line = 0x1a
2480 */
2481
2482#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
2483#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
2484
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002485static struct snd_kcontrol_new alc880_asus_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002486 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002487 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002488 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002489 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002490 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2491 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01002492 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2493 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002494 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2495 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2496 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2497 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2498 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2499 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002500 {
2501 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2502 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01002503 .info = alc_ch_mode_info,
2504 .get = alc_ch_mode_get,
2505 .put = alc_ch_mode_put,
Takashi Iwai16ded522005-06-10 19:58:24 +02002506 },
2507 { } /* end */
2508};
2509
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002510/*
2511 * ALC880 ASUS W1V model
2512 *
2513 * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
2514 * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
2515 * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
2516 */
2517
2518/* additional mixers to alc880_asus_mixer */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01002519static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
Takashi Iwai16ded522005-06-10 19:58:24 +02002520 HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
2521 HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02002522 { } /* end */
2523};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002524
Kailang Yangdf694da2005-12-05 19:42:22 +01002525/* TCL S700 */
2526static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
2527 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2528 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2529 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
2530 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
2531 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
2532 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
2533 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
2534 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
2535 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01002536 { } /* end */
2537};
2538
Kailang Yangccc656c2006-10-17 12:32:26 +02002539/* Uniwill */
2540static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002541 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2542 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2543 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2544 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002545 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2546 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2547 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2548 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2549 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2550 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2551 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2552 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2553 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2554 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2555 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2556 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002557 {
2558 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2559 .name = "Channel Mode",
2560 .info = alc_ch_mode_info,
2561 .get = alc_ch_mode_get,
2562 .put = alc_ch_mode_put,
2563 },
2564 { } /* end */
2565};
2566
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01002567static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
2568 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2569 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2570 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2571 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
2572 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2573 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2574 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2575 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2576 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2577 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
2578 { } /* end */
2579};
2580
Kailang Yangccc656c2006-10-17 12:32:26 +02002581static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002582 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2583 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
2584 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2585 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02002586 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2587 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2588 { } /* end */
2589};
2590
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591/*
Takashi Iwai2134ea42008-01-10 16:53:55 +01002592 * virtual master controls
2593 */
2594
2595/*
2596 * slave controls for virtual master
2597 */
2598static const char *alc_slave_vols[] = {
2599 "Front Playback Volume",
2600 "Surround Playback Volume",
2601 "Center Playback Volume",
2602 "LFE Playback Volume",
2603 "Side Playback Volume",
2604 "Headphone Playback Volume",
2605 "Speaker Playback Volume",
2606 "Mono Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002607 "Line-Out Playback Volume",
Takashi Iwai26f5df22008-11-03 17:39:46 +01002608 "PCM Playback Volume",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002609 NULL,
2610};
2611
2612static const char *alc_slave_sws[] = {
2613 "Front Playback Switch",
2614 "Surround Playback Switch",
2615 "Center Playback Switch",
2616 "LFE Playback Switch",
2617 "Side Playback Switch",
2618 "Headphone Playback Switch",
2619 "Speaker Playback Switch",
2620 "Mono Playback Switch",
Takashi Iwaiedb54a52008-01-29 12:47:02 +01002621 "IEC958 Playback Switch",
Takashi Iwai23033b22009-12-08 12:36:52 +01002622 "Line-Out Playback Switch",
2623 "PCM Playback Switch",
Takashi Iwai2134ea42008-01-10 16:53:55 +01002624 NULL,
2625};
2626
2627/*
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002628 * build control elements
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 */
Takashi Iwai603c4012008-07-30 15:01:44 +02002630
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002631#define NID_MAPPING (-1)
2632
2633#define SUBDEV_SPEAKER_ (0 << 6)
2634#define SUBDEV_HP_ (1 << 6)
2635#define SUBDEV_LINE_ (2 << 6)
2636#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f))
2637#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f))
2638#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f))
2639
Takashi Iwai603c4012008-07-30 15:01:44 +02002640static void alc_free_kctls(struct hda_codec *codec);
2641
Takashi Iwai67d634c2009-11-16 15:35:59 +01002642#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002643/* additional beep mixers; the actual parameters are overwritten at build */
2644static struct snd_kcontrol_new alc_beep_mixer[] = {
2645 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +02002646 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002647 { } /* end */
2648};
Takashi Iwai67d634c2009-11-16 15:35:59 +01002649#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002650
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651static int alc_build_controls(struct hda_codec *codec)
2652{
2653 struct alc_spec *spec = codec->spec;
Takashi Iwai2f44f842010-06-22 11:12:32 +02002654 struct snd_kcontrol *kctl = NULL;
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002655 struct snd_kcontrol_new *knew;
2656 int i, j, err;
2657 unsigned int u;
2658 hda_nid_t nid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
2660 for (i = 0; i < spec->num_mixers; i++) {
2661 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
2662 if (err < 0)
2663 return err;
2664 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01002665 if (spec->cap_mixer) {
2666 err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
2667 if (err < 0)
2668 return err;
2669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 if (spec->multiout.dig_out_nid) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002671 err = snd_hda_create_spdif_out_ctls(codec,
2672 spec->multiout.dig_out_nid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 if (err < 0)
2674 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002675 if (!spec->no_analog) {
2676 err = snd_hda_create_spdif_share_sw(codec,
2677 &spec->multiout);
2678 if (err < 0)
2679 return err;
2680 spec->multiout.share_spdif = 1;
2681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 }
2683 if (spec->dig_in_nid) {
2684 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
2685 if (err < 0)
2686 return err;
2687 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01002688
Takashi Iwai67d634c2009-11-16 15:35:59 +01002689#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002690 /* create beep controls if needed */
2691 if (spec->beep_amp) {
2692 struct snd_kcontrol_new *knew;
2693 for (knew = alc_beep_mixer; knew->name; knew++) {
2694 struct snd_kcontrol *kctl;
2695 kctl = snd_ctl_new1(knew, codec);
2696 if (!kctl)
2697 return -ENOMEM;
2698 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01002699 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002700 if (err < 0)
2701 return err;
2702 }
2703 }
Takashi Iwai67d634c2009-11-16 15:35:59 +01002704#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01002705
Takashi Iwai2134ea42008-01-10 16:53:55 +01002706 /* if we have no master control, let's create it */
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002707 if (!spec->no_analog &&
2708 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002709 unsigned int vmaster_tlv[4];
Takashi Iwai2134ea42008-01-10 16:53:55 +01002710 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002711 HDA_OUTPUT, vmaster_tlv);
Takashi Iwai2134ea42008-01-10 16:53:55 +01002712 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai1c82ed12008-02-18 13:05:50 +01002713 vmaster_tlv, alc_slave_vols);
Takashi Iwai2134ea42008-01-10 16:53:55 +01002714 if (err < 0)
2715 return err;
2716 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +01002717 if (!spec->no_analog &&
2718 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
Takashi Iwai2134ea42008-01-10 16:53:55 +01002719 err = snd_hda_add_vmaster(codec, "Master Playback Switch",
2720 NULL, alc_slave_sws);
2721 if (err < 0)
2722 return err;
2723 }
2724
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002725 /* assign Capture Source enums to NID */
Takashi Iwaifbe618f2010-06-11 11:24:58 +02002726 if (spec->capsrc_nids || spec->adc_nids) {
2727 kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
2728 if (!kctl)
2729 kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
2730 for (i = 0; kctl && i < kctl->count; i++) {
2731 hda_nid_t *nids = spec->capsrc_nids;
2732 if (!nids)
2733 nids = spec->adc_nids;
2734 err = snd_hda_add_nid(codec, kctl, i, nids[i]);
2735 if (err < 0)
2736 return err;
2737 }
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01002738 }
2739 if (spec->cap_mixer) {
2740 const char *kname = kctl ? kctl->id.name : NULL;
2741 for (knew = spec->cap_mixer; knew->name; knew++) {
2742 if (kname && strcmp(knew->name, kname) == 0)
2743 continue;
2744 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
2745 for (i = 0; kctl && i < kctl->count; i++) {
2746 err = snd_hda_add_nid(codec, kctl, i,
2747 spec->adc_nids[i]);
2748 if (err < 0)
2749 return err;
2750 }
2751 }
2752 }
2753
2754 /* other nid->control mapping */
2755 for (i = 0; i < spec->num_mixers; i++) {
2756 for (knew = spec->mixers[i]; knew->name; knew++) {
2757 if (knew->iface != NID_MAPPING)
2758 continue;
2759 kctl = snd_hda_find_mixer_ctl(codec, knew->name);
2760 if (kctl == NULL)
2761 continue;
2762 u = knew->subdevice;
2763 for (j = 0; j < 4; j++, u >>= 8) {
2764 nid = u & 0x3f;
2765 if (nid == 0)
2766 continue;
2767 switch (u & 0xc0) {
2768 case SUBDEV_SPEAKER_:
2769 nid = spec->autocfg.speaker_pins[nid];
2770 break;
2771 case SUBDEV_LINE_:
2772 nid = spec->autocfg.line_out_pins[nid];
2773 break;
2774 case SUBDEV_HP_:
2775 nid = spec->autocfg.hp_pins[nid];
2776 break;
2777 default:
2778 continue;
2779 }
2780 err = snd_hda_add_nid(codec, kctl, 0, nid);
2781 if (err < 0)
2782 return err;
2783 }
2784 u = knew->private_value;
2785 for (j = 0; j < 4; j++, u >>= 8) {
2786 nid = u & 0xff;
2787 if (nid == 0)
2788 continue;
2789 err = snd_hda_add_nid(codec, kctl, 0, nid);
2790 if (err < 0)
2791 return err;
2792 }
2793 }
2794 }
Takashi Iwaibae84e72010-03-22 08:30:20 +01002795
2796 alc_free_kctls(codec); /* no longer needed */
2797
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 return 0;
2799}
2800
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002801
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802/*
2803 * initialize the codec volumes, etc
2804 */
2805
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002806/*
2807 * generic initialization of ADC, input mixers and output mixers
2808 */
2809static struct hda_verb alc880_volume_init_verbs[] = {
2810 /*
2811 * Unmute ADC0-2 and set the default input to mic-in
2812 */
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002813 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002814 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002815 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002816 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02002817 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002818 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002820 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2821 * mixer widget
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002822 * Note: PASD motherboards uses the Line In 2 as the input for front
2823 * panel mic (mic 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002825 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02002826 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2827 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2828 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2829 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2830 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2831 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2832 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002834 /*
2835 * Set up output mixers (0x0c - 0x0f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002837 /* set vol=0 to output mixers */
2838 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2839 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2840 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2841 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2842 /* set up input amps for analog loopback */
2843 /* Amp Indices: DAC = 0, mixer = 1 */
Takashi Iwai05acb862005-06-10 19:50:25 +02002844 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2845 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002846 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2847 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002848 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2849 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai05acb862005-06-10 19:50:25 +02002850 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2851 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852
2853 { }
2854};
2855
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002856/*
2857 * 3-stack pin configuration:
2858 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
2859 */
2860static struct hda_verb alc880_pin_3stack_init_verbs[] = {
2861 /*
2862 * preset connection lists of input pins
2863 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
2864 */
2865 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
2866 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2867 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
2868
2869 /*
2870 * Set pin mode and muting
2871 */
2872 /* set front pin widgets 0x14 for output */
2873 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2874 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2875 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2876 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2877 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2878 /* Mic2 (as headphone out) for HP output */
2879 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2880 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2881 /* Line In pin widget for input */
2882 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2883 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2884 /* Line2 (as front mic) pin widget for input and vref at 80% */
2885 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2886 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2887 /* CD pin widget for input */
2888 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2889
2890 { }
2891};
2892
2893/*
2894 * 5-stack pin configuration:
2895 * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
2896 * line-in/side = 0x1a, f-mic = 0x1b
2897 */
2898static struct hda_verb alc880_pin_5stack_init_verbs[] = {
2899 /*
2900 * preset connection lists of input pins
2901 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
2902 */
2903 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2904 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
2905
2906 /*
2907 * Set pin mode and muting
2908 */
2909 /* set pin widgets 0x14-0x17 for output */
Takashi Iwai05acb862005-06-10 19:50:25 +02002910 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2911 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2912 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2913 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002914 /* unmute pins for output (no gain on this amp) */
2915 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2916 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2917 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2918 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2919
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 /* Mic1 (rear panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02002921 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002922 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2923 /* Mic2 (as headphone out) for HP output */
2924 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai05acb862005-06-10 19:50:25 +02002925 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002926 /* Line In pin widget for input */
2927 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2928 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2929 /* Line2 (as front mic) pin widget for input and vref at 80% */
2930 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2931 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2932 /* CD pin widget for input */
2933 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934
2935 { }
2936};
2937
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002938/*
2939 * W810 pin configuration:
2940 * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
2941 */
2942static struct hda_verb alc880_pin_w810_init_verbs[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 /* hphone/speaker input selector: front DAC */
2944 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
2945
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002946 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2947 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2948 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2949 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2950 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2951 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2952
2953 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai05acb862005-06-10 19:50:25 +02002954 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956 { }
2957};
2958
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002959/*
2960 * Z71V pin configuration:
2961 * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
2962 */
2963static struct hda_verb alc880_pin_z71v_init_verbs[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02002964 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002965 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai05acb862005-06-10 19:50:25 +02002966 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002967 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002968
Takashi Iwai16ded522005-06-10 19:58:24 +02002969 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002970 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai16ded522005-06-10 19:58:24 +02002971 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002972 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaidfc0ff62005-05-12 14:31:49 +02002973
2974 { }
2975};
2976
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002977/*
2978 * 6-stack pin configuration:
Takashi Iwai9c7f8522006-06-28 15:08:22 +02002979 * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
2980 * f-mic = 0x19, line = 0x1a, HP = 0x1b
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002981 */
2982static struct hda_verb alc880_pin_6stack_init_verbs[] = {
2983 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
2984
Takashi Iwai16ded522005-06-10 19:58:24 +02002985 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002986 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002987 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002988 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002989 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002990 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002991 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002992 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2993
Takashi Iwai16ded522005-06-10 19:58:24 +02002994 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002995 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002996 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002997 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02002998 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02002999 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02003000 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai16ded522005-06-10 19:58:24 +02003001 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai16ded522005-06-10 19:58:24 +02003002 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yangea1fb292008-08-26 12:58:38 +02003003
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003004 { }
3005};
Takashi Iwai16ded522005-06-10 19:58:24 +02003006
Kailang Yangccc656c2006-10-17 12:32:26 +02003007/*
3008 * Uniwill pin configuration:
3009 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
3010 * line = 0x1a
3011 */
3012static struct hda_verb alc880_uniwill_init_verbs[] = {
3013 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3014
3015 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3016 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3017 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3018 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3019 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3020 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3021 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3022 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3023 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3024 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3025 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3026 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3027 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3028 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3029
3030 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3031 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3032 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3033 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3034 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3035 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3036 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
3037 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
3038 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3039
3040 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3041 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
3042
3043 { }
3044};
3045
3046/*
3047* Uniwill P53
Kailang Yangea1fb292008-08-26 12:58:38 +02003048* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
Kailang Yangccc656c2006-10-17 12:32:26 +02003049 */
3050static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
3051 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3052
3053 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3054 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3055 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3056 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3057 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3058 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3059 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3060 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3061 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3062 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3063 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3064 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
3065
3066 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3067 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3068 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3069 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3070 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3071 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3072
3073 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3074 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
3075
3076 { }
3077};
3078
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01003079static struct hda_verb alc880_beep_init_verbs[] = {
3080 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
3081 { }
3082};
3083
Takashi Iwai458a4fa2007-05-05 12:18:40 +02003084/* auto-toggle front mic */
3085static void alc880_uniwill_mic_automute(struct hda_codec *codec)
3086{
3087 unsigned int present;
3088 unsigned char bits;
Kailang Yangccc656c2006-10-17 12:32:26 +02003089
Wu Fengguang864f92b2009-11-18 12:38:02 +08003090 present = snd_hda_jack_detect(codec, 0x18);
Takashi Iwai47fd8302007-08-10 17:11:07 +02003091 bits = present ? HDA_AMP_MUTE : 0;
3092 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
Takashi Iwai458a4fa2007-05-05 12:18:40 +02003093}
3094
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003095static void alc880_uniwill_setup(struct hda_codec *codec)
Takashi Iwai458a4fa2007-05-05 12:18:40 +02003096{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003097 struct alc_spec *spec = codec->spec;
3098
3099 spec->autocfg.hp_pins[0] = 0x14;
3100 spec->autocfg.speaker_pins[0] = 0x15;
3101 spec->autocfg.speaker_pins[0] = 0x16;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003102}
3103
3104static void alc880_uniwill_init_hook(struct hda_codec *codec)
3105{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003106 alc_automute_amp(codec);
Takashi Iwai458a4fa2007-05-05 12:18:40 +02003107 alc880_uniwill_mic_automute(codec);
Kailang Yangccc656c2006-10-17 12:32:26 +02003108}
3109
3110static void alc880_uniwill_unsol_event(struct hda_codec *codec,
3111 unsigned int res)
3112{
3113 /* Looks like the unsol event is incompatible with the standard
3114 * definition. 4bit tag is placed at 28 bit!
3115 */
Takashi Iwai458a4fa2007-05-05 12:18:40 +02003116 switch (res >> 28) {
Takashi Iwai458a4fa2007-05-05 12:18:40 +02003117 case ALC880_MIC_EVENT:
3118 alc880_uniwill_mic_automute(codec);
3119 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003120 default:
3121 alc_automute_amp_unsol_event(codec, res);
3122 break;
Takashi Iwai458a4fa2007-05-05 12:18:40 +02003123 }
Kailang Yangccc656c2006-10-17 12:32:26 +02003124}
3125
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003126static void alc880_uniwill_p53_setup(struct hda_codec *codec)
Kailang Yangccc656c2006-10-17 12:32:26 +02003127{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003128 struct alc_spec *spec = codec->spec;
Kailang Yangccc656c2006-10-17 12:32:26 +02003129
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003130 spec->autocfg.hp_pins[0] = 0x14;
3131 spec->autocfg.speaker_pins[0] = 0x15;
Kailang Yangccc656c2006-10-17 12:32:26 +02003132}
3133
3134static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
3135{
3136 unsigned int present;
Kailang Yangea1fb292008-08-26 12:58:38 +02003137
Kailang Yangccc656c2006-10-17 12:32:26 +02003138 present = snd_hda_codec_read(codec, 0x21, 0,
Takashi Iwai47fd8302007-08-10 17:11:07 +02003139 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
3140 present &= HDA_AMP_VOLMASK;
3141 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
3142 HDA_AMP_VOLMASK, present);
3143 snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
3144 HDA_AMP_VOLMASK, present);
Kailang Yangccc656c2006-10-17 12:32:26 +02003145}
Takashi Iwai47fd8302007-08-10 17:11:07 +02003146
Kailang Yangccc656c2006-10-17 12:32:26 +02003147static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
3148 unsigned int res)
3149{
3150 /* Looks like the unsol event is incompatible with the standard
3151 * definition. 4bit tag is placed at 28 bit!
3152 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02003153 if ((res >> 28) == ALC880_DCVOL_EVENT)
Kailang Yangccc656c2006-10-17 12:32:26 +02003154 alc880_uniwill_p53_dcvol_automute(codec);
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003155 else
3156 alc_automute_amp_unsol_event(codec, res);
Kailang Yangccc656c2006-10-17 12:32:26 +02003157}
3158
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003159/*
3160 * F1734 pin configuration:
3161 * HP = 0x14, speaker-out = 0x15, mic = 0x18
3162 */
3163static struct hda_verb alc880_pin_f1734_init_verbs[] = {
Michael Gruberee7a9c72008-03-10 11:30:59 +01003164 {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003165 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
3166 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
3167 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
3168 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
3169
3170 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3171 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3172 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3173 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3174
3175 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3176 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Michael Gruberee7a9c72008-03-10 11:30:59 +01003177 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003178 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3179 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3180 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3181 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3182 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3183 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai16ded522005-06-10 19:58:24 +02003184
Takashi Iwai937b4162008-02-11 14:52:36 +01003185 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
3186 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
3187
Takashi Iwai16ded522005-06-10 19:58:24 +02003188 { }
3189};
3190
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003191/*
3192 * ASUS pin configuration:
3193 * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
3194 */
3195static struct hda_verb alc880_pin_asus_init_verbs[] = {
3196 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
3197 {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
3198 {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
3199 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
3200
3201 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3202 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3203 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3204 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3205 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3206 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3207 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3208 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3209
3210 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3211 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3212 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3213 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3214 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3215 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3216 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3217 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3218 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yangea1fb292008-08-26 12:58:38 +02003219
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003220 { }
3221};
3222
3223/* Enable GPIO mask and set output */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02003224#define alc880_gpio1_init_verbs alc_gpio1_init_verbs
3225#define alc880_gpio2_init_verbs alc_gpio2_init_verbs
David Heidelberger64a8be72009-06-08 16:15:18 +02003226#define alc880_gpio3_init_verbs alc_gpio3_init_verbs
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003227
Kailang Yangdf694da2005-12-05 19:42:22 +01003228/* Clevo m520g init */
3229static struct hda_verb alc880_pin_clevo_init_verbs[] = {
3230 /* headphone output */
3231 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3232 /* line-out */
3233 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3234 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3235 /* Line-in */
3236 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3237 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3238 /* CD */
3239 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3240 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3241 /* Mic1 (rear panel) */
3242 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3243 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3244 /* Mic2 (front panel) */
3245 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3246 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3247 /* headphone */
3248 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3249 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3250 /* change to EAPD mode */
3251 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3252 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3253
3254 { }
3255};
3256
3257static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
Takashi Iwai4b146cb2006-07-28 14:42:36 +02003258 /* change to EAPD mode */
3259 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3260 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3261
Kailang Yangdf694da2005-12-05 19:42:22 +01003262 /* Headphone output */
3263 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3264 /* Front output*/
3265 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3266 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
3267
3268 /* Line In pin widget for input */
3269 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3270 /* CD pin widget for input */
3271 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3272 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3273 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3274
3275 /* change to EAPD mode */
3276 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3277 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
3278
3279 { }
3280};
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003281
3282/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003283 * LG m1 express dual
3284 *
3285 * Pin assignment:
3286 * Rear Line-In/Out (blue): 0x14
3287 * Build-in Mic-In: 0x15
3288 * Speaker-out: 0x17
3289 * HP-Out (green): 0x1b
3290 * Mic-In/Out (red): 0x19
3291 * SPDIF-Out: 0x1e
3292 */
3293
3294/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
3295static hda_nid_t alc880_lg_dac_nids[3] = {
3296 0x05, 0x02, 0x03
3297};
3298
3299/* seems analog CD is not working */
3300static struct hda_input_mux alc880_lg_capture_source = {
3301 .num_items = 3,
3302 .items = {
3303 { "Mic", 0x1 },
3304 { "Line", 0x5 },
3305 { "Internal Mic", 0x6 },
3306 },
3307};
3308
3309/* 2,4,6 channel modes */
3310static struct hda_verb alc880_lg_ch2_init[] = {
3311 /* set line-in and mic-in to input */
3312 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
3313 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3314 { }
3315};
3316
3317static struct hda_verb alc880_lg_ch4_init[] = {
3318 /* set line-in to out and mic-in to input */
3319 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3320 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
3321 { }
3322};
3323
3324static struct hda_verb alc880_lg_ch6_init[] = {
3325 /* set line-in and mic-in to output */
3326 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3327 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
3328 { }
3329};
3330
3331static struct hda_channel_mode alc880_lg_ch_modes[3] = {
3332 { 2, alc880_lg_ch2_init },
3333 { 4, alc880_lg_ch4_init },
3334 { 6, alc880_lg_ch6_init },
3335};
3336
3337static struct snd_kcontrol_new alc880_lg_mixer[] = {
Takashi Iwai2134ea42008-01-10 16:53:55 +01003338 HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3339 HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003340 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3341 HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
3342 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
3343 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
3344 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
3345 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
3346 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3347 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
3348 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
3349 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
3350 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
3351 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
3352 {
3353 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3354 .name = "Channel Mode",
3355 .info = alc_ch_mode_info,
3356 .get = alc_ch_mode_get,
3357 .put = alc_ch_mode_put,
3358 },
3359 { } /* end */
3360};
3361
3362static struct hda_verb alc880_lg_init_verbs[] = {
3363 /* set capture source to mic-in */
3364 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3365 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3366 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3367 /* mute all amp mixer inputs */
3368 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
Takashi Iwaicb53c622007-08-10 17:21:45 +02003369 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3370 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003371 /* line-in to input */
3372 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3373 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3374 /* built-in mic */
3375 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3376 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3377 /* speaker-out */
3378 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3379 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3380 /* mic-in to input */
3381 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
3382 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3383 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3384 /* HP-out */
3385 {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
3386 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3387 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3388 /* jack sense */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003389 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003390 { }
3391};
3392
3393/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003394static void alc880_lg_setup(struct hda_codec *codec)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003395{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003396 struct alc_spec *spec = codec->spec;
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003397
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003398 spec->autocfg.hp_pins[0] = 0x1b;
3399 spec->autocfg.speaker_pins[0] = 0x17;
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003400}
3401
3402/*
Takashi Iwaid6815182006-03-23 16:06:23 +01003403 * LG LW20
3404 *
3405 * Pin assignment:
3406 * Speaker-out: 0x14
3407 * Mic-In: 0x18
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003408 * Built-in Mic-In: 0x19
3409 * Line-In: 0x1b
3410 * HP-Out: 0x1a
Takashi Iwaid6815182006-03-23 16:06:23 +01003411 * SPDIF-Out: 0x1e
3412 */
3413
Takashi Iwaid6815182006-03-23 16:06:23 +01003414static struct hda_input_mux alc880_lg_lw_capture_source = {
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003415 .num_items = 3,
Takashi Iwaid6815182006-03-23 16:06:23 +01003416 .items = {
3417 { "Mic", 0x0 },
3418 { "Internal Mic", 0x1 },
Claudio Matsuokae4f41da2007-07-13 11:51:06 +02003419 { "Line In", 0x2 },
Takashi Iwaid6815182006-03-23 16:06:23 +01003420 },
3421};
3422
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003423#define alc880_lg_lw_modes alc880_threestack_modes
3424
Takashi Iwaid6815182006-03-23 16:06:23 +01003425static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003426 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3427 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
3428 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
3429 HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
3430 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
3431 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3432 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
3433 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
3434 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3435 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwaid6815182006-03-23 16:06:23 +01003436 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3437 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3438 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
3439 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003440 {
3441 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3442 .name = "Channel Mode",
3443 .info = alc_ch_mode_info,
3444 .get = alc_ch_mode_get,
3445 .put = alc_ch_mode_put,
3446 },
Takashi Iwaid6815182006-03-23 16:06:23 +01003447 { } /* end */
3448};
3449
3450static struct hda_verb alc880_lg_lw_init_verbs[] = {
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02003451 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3452 {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
3453 {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
3454
Takashi Iwaid6815182006-03-23 16:06:23 +01003455 /* set capture source to mic-in */
3456 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3457 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3458 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwaicb53c622007-08-10 17:21:45 +02003459 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Takashi Iwaid6815182006-03-23 16:06:23 +01003460 /* speaker-out */
3461 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3462 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3463 /* HP-out */
Takashi Iwaid6815182006-03-23 16:06:23 +01003464 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3465 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3466 /* mic-in to input */
3467 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3468 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3469 /* built-in mic */
3470 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3471 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3472 /* jack sense */
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003473 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaid6815182006-03-23 16:06:23 +01003474 { }
3475};
3476
3477/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003478static void alc880_lg_lw_setup(struct hda_codec *codec)
Takashi Iwaid6815182006-03-23 16:06:23 +01003479{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003480 struct alc_spec *spec = codec->spec;
Takashi Iwaid6815182006-03-23 16:06:23 +01003481
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003482 spec->autocfg.hp_pins[0] = 0x1b;
3483 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwaid6815182006-03-23 16:06:23 +01003484}
3485
Takashi Iwaidf99cd32008-04-25 15:25:04 +02003486static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
3487 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3488 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
3489 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3490 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3491 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
3492 HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
3493 { } /* end */
3494};
3495
3496static struct hda_input_mux alc880_medion_rim_capture_source = {
3497 .num_items = 2,
3498 .items = {
3499 { "Mic", 0x0 },
3500 { "Internal Mic", 0x1 },
3501 },
3502};
3503
3504static struct hda_verb alc880_medion_rim_init_verbs[] = {
3505 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
3506
3507 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3508 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3509
3510 /* Mic1 (rear panel) pin widget for input and vref at 80% */
3511 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3512 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3513 /* Mic2 (as headphone out) for HP output */
3514 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3515 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3516 /* Internal Speaker */
3517 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3518 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3519
3520 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
3521 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
3522
3523 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
3524 { }
3525};
3526
3527/* toggle speaker-output according to the hp-jack state */
3528static void alc880_medion_rim_automute(struct hda_codec *codec)
3529{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003530 struct alc_spec *spec = codec->spec;
3531 alc_automute_amp(codec);
3532 /* toggle EAPD */
3533 if (spec->jack_present)
Takashi Iwaidf99cd32008-04-25 15:25:04 +02003534 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
3535 else
3536 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
3537}
3538
3539static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
3540 unsigned int res)
3541{
3542 /* Looks like the unsol event is incompatible with the standard
3543 * definition. 4bit tag is placed at 28 bit!
3544 */
3545 if ((res >> 28) == ALC880_HP_EVENT)
3546 alc880_medion_rim_automute(codec);
3547}
3548
Takashi Iwai4f5d17062009-08-11 18:17:46 +02003549static void alc880_medion_rim_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003550{
3551 struct alc_spec *spec = codec->spec;
3552
3553 spec->autocfg.hp_pins[0] = 0x14;
3554 spec->autocfg.speaker_pins[0] = 0x1b;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02003555}
3556
Takashi Iwaicb53c622007-08-10 17:21:45 +02003557#ifdef CONFIG_SND_HDA_POWER_SAVE
3558static struct hda_amp_list alc880_loopbacks[] = {
3559 { 0x0b, HDA_INPUT, 0 },
3560 { 0x0b, HDA_INPUT, 1 },
3561 { 0x0b, HDA_INPUT, 2 },
3562 { 0x0b, HDA_INPUT, 3 },
3563 { 0x0b, HDA_INPUT, 4 },
3564 { } /* end */
3565};
3566
3567static struct hda_amp_list alc880_lg_loopbacks[] = {
3568 { 0x0b, HDA_INPUT, 1 },
3569 { 0x0b, HDA_INPUT, 6 },
3570 { 0x0b, HDA_INPUT, 7 },
3571 { } /* end */
3572};
3573#endif
3574
Takashi Iwaid6815182006-03-23 16:06:23 +01003575/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003576 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003577 */
Takashi Iwai16ded522005-06-10 19:58:24 +02003578
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579static int alc_init(struct hda_codec *codec)
3580{
3581 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003582 unsigned int i;
3583
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02003584 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02003585 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02003586
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003587 for (i = 0; i < spec->num_init_verbs; i++)
3588 snd_hda_sequence_write(codec, spec->init_verbs[i]);
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003589
3590 if (spec->init_hook)
3591 spec->init_hook(codec);
3592
Takashi Iwaiad358792010-03-30 18:00:59 +02003593#ifdef CONFIG_SND_HDA_POWER_SAVE
3594 if (codec->patch_ops.check_power_status)
3595 codec->patch_ops.check_power_status(codec, 0x01);
3596#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 return 0;
3598}
3599
Takashi Iwaiae6b8132006-03-03 16:47:17 +01003600static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
3601{
3602 struct alc_spec *spec = codec->spec;
3603
3604 if (spec->unsol_event)
3605 spec->unsol_event(codec, res);
3606}
3607
Takashi Iwaicb53c622007-08-10 17:21:45 +02003608#ifdef CONFIG_SND_HDA_POWER_SAVE
3609static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
3610{
3611 struct alc_spec *spec = codec->spec;
3612 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
3613}
3614#endif
3615
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616/*
3617 * Analog playback callbacks
3618 */
3619static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
3620 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003621 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622{
3623 struct alc_spec *spec = codec->spec;
Takashi Iwai9a081602008-02-12 18:37:26 +01003624 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
3625 hinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626}
3627
3628static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3629 struct hda_codec *codec,
3630 unsigned int stream_tag,
3631 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003632 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633{
3634 struct alc_spec *spec = codec->spec;
Takashi Iwai9c7f8522006-06-28 15:08:22 +02003635 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3636 stream_tag, format, substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637}
3638
3639static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3640 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003641 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642{
3643 struct alc_spec *spec = codec->spec;
3644 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3645}
3646
3647/*
3648 * Digital out
3649 */
3650static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3651 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003652 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653{
3654 struct alc_spec *spec = codec->spec;
3655 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3656}
3657
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003658static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3659 struct hda_codec *codec,
3660 unsigned int stream_tag,
3661 unsigned int format,
3662 struct snd_pcm_substream *substream)
3663{
3664 struct alc_spec *spec = codec->spec;
3665 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3666 stream_tag, format, substream);
3667}
3668
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01003669static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3670 struct hda_codec *codec,
3671 struct snd_pcm_substream *substream)
3672{
3673 struct alc_spec *spec = codec->spec;
3674 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
3675}
3676
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
3678 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003679 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680{
3681 struct alc_spec *spec = codec->spec;
3682 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
3683}
3684
3685/*
3686 * Analog capture
3687 */
Takashi Iwai63300792008-01-24 15:31:36 +01003688static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 struct hda_codec *codec,
3690 unsigned int stream_tag,
3691 unsigned int format,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003692 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693{
3694 struct alc_spec *spec = codec->spec;
3695
Takashi Iwai63300792008-01-24 15:31:36 +01003696 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 stream_tag, 0, format);
3698 return 0;
3699}
3700
Takashi Iwai63300792008-01-24 15:31:36 +01003701static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 struct hda_codec *codec,
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01003703 struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704{
3705 struct alc_spec *spec = codec->spec;
3706
Takashi Iwai888afa12008-03-18 09:57:50 +01003707 snd_hda_codec_cleanup_stream(codec,
3708 spec->adc_nids[substream->number + 1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 return 0;
3710}
3711
Takashi Iwai840b64c2010-07-13 22:49:01 +02003712/* analog capture with dynamic dual-adc changes */
3713static int dualmic_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3714 struct hda_codec *codec,
3715 unsigned int stream_tag,
3716 unsigned int format,
3717 struct snd_pcm_substream *substream)
3718{
3719 struct alc_spec *spec = codec->spec;
3720 spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
3721 spec->cur_adc_stream_tag = stream_tag;
3722 spec->cur_adc_format = format;
3723 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
3724 return 0;
3725}
3726
3727static int dualmic_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3728 struct hda_codec *codec,
3729 struct snd_pcm_substream *substream)
3730{
3731 struct alc_spec *spec = codec->spec;
3732 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
3733 spec->cur_adc = 0;
3734 return 0;
3735}
3736
3737static struct hda_pcm_stream dualmic_pcm_analog_capture = {
3738 .substreams = 1,
3739 .channels_min = 2,
3740 .channels_max = 2,
3741 .nid = 0, /* fill later */
3742 .ops = {
3743 .prepare = dualmic_capture_pcm_prepare,
3744 .cleanup = dualmic_capture_pcm_cleanup
3745 },
3746};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747
3748/*
3749 */
3750static struct hda_pcm_stream alc880_pcm_analog_playback = {
3751 .substreams = 1,
3752 .channels_min = 2,
3753 .channels_max = 8,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003754 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 .ops = {
3756 .open = alc880_playback_pcm_open,
3757 .prepare = alc880_playback_pcm_prepare,
3758 .cleanup = alc880_playback_pcm_cleanup
3759 },
3760};
3761
3762static struct hda_pcm_stream alc880_pcm_analog_capture = {
Takashi Iwai63300792008-01-24 15:31:36 +01003763 .substreams = 1,
3764 .channels_min = 2,
3765 .channels_max = 2,
3766 /* NID is set in alc_build_pcms */
3767};
3768
3769static struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
3770 .substreams = 1,
3771 .channels_min = 2,
3772 .channels_max = 2,
3773 /* NID is set in alc_build_pcms */
3774};
3775
3776static struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
3777 .substreams = 2, /* can be overridden */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 .channels_min = 2,
3779 .channels_max = 2,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003780 /* NID is set in alc_build_pcms */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 .ops = {
Takashi Iwai63300792008-01-24 15:31:36 +01003782 .prepare = alc880_alt_capture_pcm_prepare,
3783 .cleanup = alc880_alt_capture_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 },
3785};
3786
3787static struct hda_pcm_stream alc880_pcm_digital_playback = {
3788 .substreams = 1,
3789 .channels_min = 2,
3790 .channels_max = 2,
3791 /* NID is set in alc_build_pcms */
3792 .ops = {
3793 .open = alc880_dig_playback_pcm_open,
Takashi Iwai6b97eb42007-04-05 14:51:48 +02003794 .close = alc880_dig_playback_pcm_close,
Takashi Iwai9b5f12e2009-02-13 11:47:37 +01003795 .prepare = alc880_dig_playback_pcm_prepare,
3796 .cleanup = alc880_dig_playback_pcm_cleanup
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 },
3798};
3799
3800static struct hda_pcm_stream alc880_pcm_digital_capture = {
3801 .substreams = 1,
3802 .channels_min = 2,
3803 .channels_max = 2,
3804 /* NID is set in alc_build_pcms */
3805};
3806
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01003807/* Used by alc_build_pcms to flag that a PCM has no playback stream */
Takashi Iwai63300792008-01-24 15:31:36 +01003808static struct hda_pcm_stream alc_pcm_null_stream = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01003809 .substreams = 0,
3810 .channels_min = 0,
3811 .channels_max = 0,
3812};
3813
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814static int alc_build_pcms(struct hda_codec *codec)
3815{
3816 struct alc_spec *spec = codec->spec;
3817 struct hda_pcm *info = spec->pcm_rec;
3818 int i;
3819
3820 codec->num_pcms = 1;
3821 codec->pcm_info = info;
3822
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003823 if (spec->no_analog)
3824 goto skip_analog;
3825
Takashi Iwai812a2cc2009-05-16 10:00:49 +02003826 snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
3827 "%s Analog", codec->chip_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 info->name = spec->stream_name_analog;
Kailang Yang274693f2009-12-03 10:07:50 +01003829
Takashi Iwai4a471b72005-12-07 13:56:29 +01003830 if (spec->stream_analog_playback) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003831 if (snd_BUG_ON(!spec->multiout.dac_nids))
3832 return -EINVAL;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003833 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
3834 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
3835 }
3836 if (spec->stream_analog_capture) {
Takashi Iwaida3cec32008-08-08 17:12:14 +02003837 if (snd_BUG_ON(!spec->adc_nids))
3838 return -EINVAL;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003839 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
3840 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
3841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
Takashi Iwai4a471b72005-12-07 13:56:29 +01003843 if (spec->channel_mode) {
3844 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
3845 for (i = 0; i < spec->num_channel_mode; i++) {
3846 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
3847 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
3848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 }
3850 }
3851
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003852 skip_analog:
Takashi Iwaie08a0072006-09-07 17:52:14 +02003853 /* SPDIF for stream index #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
Takashi Iwai812a2cc2009-05-16 10:00:49 +02003855 snprintf(spec->stream_name_digital,
3856 sizeof(spec->stream_name_digital),
3857 "%s Digital", codec->chip_name);
Takashi Iwaie08a0072006-09-07 17:52:14 +02003858 codec->num_pcms = 2;
Wu Fengguangb25c9da2009-02-06 15:02:27 +08003859 codec->slave_dig_outs = spec->multiout.slave_dig_outs;
Takashi Iwaic06134d2006-10-11 18:49:13 +02003860 info = spec->pcm_rec + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 info->name = spec->stream_name_digital;
Takashi Iwai8c441982009-01-20 18:30:20 +01003862 if (spec->dig_out_type)
3863 info->pcm_type = spec->dig_out_type;
3864 else
3865 info->pcm_type = HDA_PCM_TYPE_SPDIF;
Takashi Iwai4a471b72005-12-07 13:56:29 +01003866 if (spec->multiout.dig_out_nid &&
3867 spec->stream_digital_playback) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
3869 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
3870 }
Takashi Iwai4a471b72005-12-07 13:56:29 +01003871 if (spec->dig_in_nid &&
3872 spec->stream_digital_capture) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
3874 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
3875 }
Takashi Iwai963f8032008-08-11 10:04:40 +02003876 /* FIXME: do we need this for all Realtek codec models? */
3877 codec->spdif_status_reset = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 }
3879
Takashi Iwaie64f14f2009-01-20 18:32:55 +01003880 if (spec->no_analog)
3881 return 0;
3882
Takashi Iwaie08a0072006-09-07 17:52:14 +02003883 /* If the use of more than one ADC is requested for the current
3884 * model, configure a second analog capture-only PCM.
3885 */
3886 /* Additional Analaog capture for index #2 */
Takashi Iwai63300792008-01-24 15:31:36 +01003887 if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||
3888 (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {
Takashi Iwaie08a0072006-09-07 17:52:14 +02003889 codec->num_pcms = 3;
Takashi Iwaic06134d2006-10-11 18:49:13 +02003890 info = spec->pcm_rec + 2;
Takashi Iwaie08a0072006-09-07 17:52:14 +02003891 info->name = spec->stream_name_analog;
Takashi Iwai63300792008-01-24 15:31:36 +01003892 if (spec->alt_dac_nid) {
3893 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3894 *spec->stream_analog_alt_playback;
3895 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
3896 spec->alt_dac_nid;
3897 } else {
3898 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3899 alc_pcm_null_stream;
3900 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
3901 }
3902 if (spec->num_adc_nids > 1) {
3903 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3904 *spec->stream_analog_alt_capture;
3905 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
3906 spec->adc_nids[1];
3907 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
3908 spec->num_adc_nids - 1;
3909 } else {
3910 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3911 alc_pcm_null_stream;
3912 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
Takashi Iwaie08a0072006-09-07 17:52:14 +02003913 }
3914 }
3915
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 return 0;
3917}
3918
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003919static inline void alc_shutup(struct hda_codec *codec)
3920{
3921 snd_hda_shutup_pins(codec);
3922}
3923
Takashi Iwai603c4012008-07-30 15:01:44 +02003924static void alc_free_kctls(struct hda_codec *codec)
3925{
3926 struct alc_spec *spec = codec->spec;
3927
3928 if (spec->kctls.list) {
3929 struct snd_kcontrol_new *kctl = spec->kctls.list;
3930 int i;
3931 for (i = 0; i < spec->kctls.used; i++)
3932 kfree(kctl[i].name);
3933 }
3934 snd_array_free(&spec->kctls);
3935}
3936
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937static void alc_free(struct hda_codec *codec)
3938{
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003939 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003940
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02003941 if (!spec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003942 return;
3943
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003944 alc_shutup(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +02003945 alc_free_kctls(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02003946 kfree(spec);
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09003947 snd_hda_detach_beep_device(codec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948}
3949
Hector Martinf5de24b2009-12-20 22:51:31 +01003950#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -05003951static void alc_power_eapd(struct hda_codec *codec)
3952{
3953 /* We currently only handle front, HP */
3954 switch (codec->vendor_id) {
3955 case 0x10ec0260:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003956 set_eapd(codec, 0x0f, 0);
3957 set_eapd(codec, 0x10, 0);
Daniel T Chenc97259d2009-12-27 18:52:08 -05003958 break;
3959 case 0x10ec0262:
3960 case 0x10ec0267:
3961 case 0x10ec0268:
3962 case 0x10ec0269:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003963 case 0x10ec0270:
Daniel T Chenc97259d2009-12-27 18:52:08 -05003964 case 0x10ec0272:
3965 case 0x10ec0660:
3966 case 0x10ec0662:
3967 case 0x10ec0663:
3968 case 0x10ec0862:
3969 case 0x10ec0889:
Takashi Iwai9e4c8492010-01-19 15:53:43 +01003970 set_eapd(codec, 0x14, 0);
3971 set_eapd(codec, 0x15, 0);
Daniel T Chenc97259d2009-12-27 18:52:08 -05003972 break;
3973 }
3974}
3975
Hector Martinf5de24b2009-12-20 22:51:31 +01003976static int alc_suspend(struct hda_codec *codec, pm_message_t state)
3977{
3978 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +01003979 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01003980 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -05003981 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +01003982 return 0;
3983}
3984#endif
3985
Takashi Iwaie044c392008-10-27 16:56:24 +01003986#ifdef SND_HDA_NEEDS_RESUME
Takashi Iwaie044c392008-10-27 16:56:24 +01003987static int alc_resume(struct hda_codec *codec)
3988{
Takashi Iwaie044c392008-10-27 16:56:24 +01003989 codec->patch_ops.init(codec);
3990 snd_hda_codec_resume_amp(codec);
3991 snd_hda_codec_resume_cache(codec);
Takashi Iwaiad358792010-03-30 18:00:59 +02003992#ifdef CONFIG_SND_HDA_POWER_SAVE
3993 if (codec->patch_ops.check_power_status)
3994 codec->patch_ops.check_power_status(codec, 0x01);
3995#endif
Takashi Iwaie044c392008-10-27 16:56:24 +01003996 return 0;
3997}
Takashi Iwaie044c392008-10-27 16:56:24 +01003998#endif
3999
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000/*
4001 */
4002static struct hda_codec_ops alc_patch_ops = {
4003 .build_controls = alc_build_controls,
4004 .build_pcms = alc_build_pcms,
4005 .init = alc_init,
4006 .free = alc_free,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004007 .unsol_event = alc_unsol_event,
Takashi Iwaie044c392008-10-27 16:56:24 +01004008#ifdef SND_HDA_NEEDS_RESUME
4009 .resume = alc_resume,
4010#endif
Takashi Iwaicb53c622007-08-10 17:21:45 +02004011#ifdef CONFIG_SND_HDA_POWER_SAVE
Hector Martinf5de24b2009-12-20 22:51:31 +01004012 .suspend = alc_suspend,
Takashi Iwaicb53c622007-08-10 17:21:45 +02004013 .check_power_status = alc_check_power_status,
4014#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -05004015 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016};
4017
Kailang Yangc027ddc2010-03-19 11:33:06 +01004018/* replace the codec chip_name with the given string */
4019static int alc_codec_rename(struct hda_codec *codec, const char *name)
4020{
4021 kfree(codec->chip_name);
4022 codec->chip_name = kstrdup(name, GFP_KERNEL);
4023 if (!codec->chip_name) {
4024 alc_free(codec);
4025 return -ENOMEM;
4026 }
4027 return 0;
4028}
4029
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004030/*
4031 * Test configuration for debugging
4032 *
4033 * Almost all inputs/outputs are enabled. I/O pins can be configured via
4034 * enum controls.
4035 */
4036#ifdef CONFIG_SND_DEBUG
4037static hda_nid_t alc880_test_dac_nids[4] = {
4038 0x02, 0x03, 0x04, 0x05
4039};
4040
4041static struct hda_input_mux alc880_test_capture_source = {
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004042 .num_items = 7,
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004043 .items = {
4044 { "In-1", 0x0 },
4045 { "In-2", 0x1 },
4046 { "In-3", 0x2 },
4047 { "In-4", 0x3 },
4048 { "CD", 0x4 },
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004049 { "Front", 0x5 },
4050 { "Surround", 0x6 },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004051 },
4052};
4053
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01004054static struct hda_channel_mode alc880_test_modes[4] = {
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004055 { 2, NULL },
Takashi Iwaifd2c3262005-05-13 17:18:42 +02004056 { 4, NULL },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004057 { 6, NULL },
Takashi Iwaifd2c3262005-05-13 17:18:42 +02004058 { 8, NULL },
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004059};
4060
Takashi Iwai9c7f8522006-06-28 15:08:22 +02004061static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
4062 struct snd_ctl_elem_info *uinfo)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004063{
4064 static char *texts[] = {
4065 "N/A", "Line Out", "HP Out",
4066 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
4067 };
4068 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4069 uinfo->count = 1;
4070 uinfo->value.enumerated.items = 8;
4071 if (uinfo->value.enumerated.item >= 8)
4072 uinfo->value.enumerated.item = 7;
4073 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
4074 return 0;
4075}
4076
Takashi Iwai9c7f8522006-06-28 15:08:22 +02004077static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
4078 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004079{
4080 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4081 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4082 unsigned int pin_ctl, item = 0;
4083
4084 pin_ctl = snd_hda_codec_read(codec, nid, 0,
4085 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4086 if (pin_ctl & AC_PINCTL_OUT_EN) {
4087 if (pin_ctl & AC_PINCTL_HP_EN)
4088 item = 2;
4089 else
4090 item = 1;
4091 } else if (pin_ctl & AC_PINCTL_IN_EN) {
4092 switch (pin_ctl & AC_PINCTL_VREFEN) {
4093 case AC_PINCTL_VREF_HIZ: item = 3; break;
4094 case AC_PINCTL_VREF_50: item = 4; break;
4095 case AC_PINCTL_VREF_GRD: item = 5; break;
4096 case AC_PINCTL_VREF_80: item = 6; break;
4097 case AC_PINCTL_VREF_100: item = 7; break;
4098 }
4099 }
4100 ucontrol->value.enumerated.item[0] = item;
4101 return 0;
4102}
4103
Takashi Iwai9c7f8522006-06-28 15:08:22 +02004104static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
4105 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004106{
4107 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4108 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4109 static unsigned int ctls[] = {
4110 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
4111 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
4112 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
4113 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
4114 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
4115 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
4116 };
4117 unsigned int old_ctl, new_ctl;
4118
4119 old_ctl = snd_hda_codec_read(codec, nid, 0,
4120 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4121 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
4122 if (old_ctl != new_ctl) {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02004123 int val;
4124 snd_hda_codec_write_cache(codec, nid, 0,
4125 AC_VERB_SET_PIN_WIDGET_CONTROL,
4126 new_ctl);
Takashi Iwai47fd8302007-08-10 17:11:07 +02004127 val = ucontrol->value.enumerated.item[0] >= 3 ?
4128 HDA_AMP_MUTE : 0;
4129 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
4130 HDA_AMP_MUTE, val);
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004131 return 1;
4132 }
4133 return 0;
4134}
4135
Takashi Iwai9c7f8522006-06-28 15:08:22 +02004136static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
4137 struct snd_ctl_elem_info *uinfo)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004138{
4139 static char *texts[] = {
4140 "Front", "Surround", "CLFE", "Side"
4141 };
4142 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4143 uinfo->count = 1;
4144 uinfo->value.enumerated.items = 4;
4145 if (uinfo->value.enumerated.item >= 4)
4146 uinfo->value.enumerated.item = 3;
4147 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
4148 return 0;
4149}
4150
Takashi Iwai9c7f8522006-06-28 15:08:22 +02004151static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
4152 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004153{
4154 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4155 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4156 unsigned int sel;
4157
4158 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
4159 ucontrol->value.enumerated.item[0] = sel & 3;
4160 return 0;
4161}
4162
Takashi Iwai9c7f8522006-06-28 15:08:22 +02004163static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
4164 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004165{
4166 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4167 hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
4168 unsigned int sel;
4169
4170 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
4171 if (ucontrol->value.enumerated.item[0] != sel) {
4172 sel = ucontrol->value.enumerated.item[0] & 3;
Takashi Iwai82beb8f2007-08-10 17:09:26 +02004173 snd_hda_codec_write_cache(codec, nid, 0,
4174 AC_VERB_SET_CONNECT_SEL, sel);
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004175 return 1;
4176 }
4177 return 0;
4178}
4179
4180#define PIN_CTL_TEST(xname,nid) { \
4181 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4182 .name = xname, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01004183 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004184 .info = alc_test_pin_ctl_info, \
4185 .get = alc_test_pin_ctl_get, \
4186 .put = alc_test_pin_ctl_put, \
4187 .private_value = nid \
4188 }
4189
4190#define PIN_SRC_TEST(xname,nid) { \
4191 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4192 .name = xname, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01004193 .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004194 .info = alc_test_pin_src_info, \
4195 .get = alc_test_pin_src_get, \
4196 .put = alc_test_pin_src_put, \
4197 .private_value = nid \
4198 }
4199
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01004200static struct snd_kcontrol_new alc880_test_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02004201 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4202 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
4203 HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
4204 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01004205 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4206 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
4207 HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
4208 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004209 PIN_CTL_TEST("Front Pin Mode", 0x14),
4210 PIN_CTL_TEST("Surround Pin Mode", 0x15),
4211 PIN_CTL_TEST("CLFE Pin Mode", 0x16),
4212 PIN_CTL_TEST("Side Pin Mode", 0x17),
4213 PIN_CTL_TEST("In-1 Pin Mode", 0x18),
4214 PIN_CTL_TEST("In-2 Pin Mode", 0x19),
4215 PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
4216 PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
4217 PIN_SRC_TEST("In-1 Pin Source", 0x18),
4218 PIN_SRC_TEST("In-2 Pin Source", 0x19),
4219 PIN_SRC_TEST("In-3 Pin Source", 0x1a),
4220 PIN_SRC_TEST("In-4 Pin Source", 0x1b),
4221 HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
4222 HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
4223 HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
4224 HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
4225 HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
4226 HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
4227 HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
4228 HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
4229 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
4230 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004231 {
4232 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4233 .name = "Channel Mode",
Kailang Yangdf694da2005-12-05 19:42:22 +01004234 .info = alc_ch_mode_info,
4235 .get = alc_ch_mode_get,
4236 .put = alc_ch_mode_put,
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004237 },
4238 { } /* end */
4239};
4240
4241static struct hda_verb alc880_test_init_verbs[] = {
4242 /* Unmute inputs of 0x0c - 0x0f */
Takashi Iwai05acb862005-06-10 19:50:25 +02004243 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4244 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4245 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4246 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4247 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4248 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4249 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4250 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004251 /* Vol output for 0x0c-0x0f */
Takashi Iwai05acb862005-06-10 19:50:25 +02004252 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4253 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4254 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4255 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004256 /* Set output pins 0x14-0x17 */
Takashi Iwai05acb862005-06-10 19:50:25 +02004257 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4258 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4259 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4260 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004261 /* Unmute output pins 0x14-0x17 */
Takashi Iwai05acb862005-06-10 19:50:25 +02004262 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4263 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4264 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4265 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004266 /* Set input pins 0x18-0x1c */
Takashi Iwai16ded522005-06-10 19:58:24 +02004267 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4268 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwai05acb862005-06-10 19:50:25 +02004269 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4270 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4271 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004272 /* Mute input pins 0x18-0x1b */
Takashi Iwai05acb862005-06-10 19:50:25 +02004273 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4274 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4275 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4276 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004277 /* ADC set up */
Takashi Iwai05acb862005-06-10 19:50:25 +02004278 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004279 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004280 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004281 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004282 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02004283 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02004284 /* Analog input/passthru */
4285 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4286 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4287 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4288 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4289 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004290 { }
4291};
4292#endif
4293
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294/*
4295 */
4296
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004297static const char *alc880_models[ALC880_MODEL_LAST] = {
4298 [ALC880_3ST] = "3stack",
4299 [ALC880_TCL_S700] = "tcl",
4300 [ALC880_3ST_DIG] = "3stack-digout",
4301 [ALC880_CLEVO] = "clevo",
4302 [ALC880_5ST] = "5stack",
4303 [ALC880_5ST_DIG] = "5stack-digout",
4304 [ALC880_W810] = "w810",
4305 [ALC880_Z71V] = "z71v",
4306 [ALC880_6ST] = "6stack",
4307 [ALC880_6ST_DIG] = "6stack-digout",
4308 [ALC880_ASUS] = "asus",
4309 [ALC880_ASUS_W1V] = "asus-w1v",
4310 [ALC880_ASUS_DIG] = "asus-dig",
4311 [ALC880_ASUS_DIG2] = "asus-dig2",
4312 [ALC880_UNIWILL_DIG] = "uniwill",
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004313 [ALC880_UNIWILL_P53] = "uniwill-p53",
4314 [ALC880_FUJITSU] = "fujitsu",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004315 [ALC880_F1734] = "F1734",
4316 [ALC880_LG] = "lg",
4317 [ALC880_LG_LW] = "lg-lw",
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004318 [ALC880_MEDION_RIM] = "medion",
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004319#ifdef CONFIG_SND_DEBUG
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004320 [ALC880_TEST] = "test",
Takashi Iwai2fa522b2005-05-12 14:51:12 +02004321#endif
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004322 [ALC880_AUTO] = "auto",
4323};
4324
4325static struct snd_pci_quirk alc880_cfg_tbl[] = {
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004326 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004327 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
4328 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
4329 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
4330 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
4331 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
4332 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
4333 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
4334 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004335 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
4336 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004337 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
4338 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
4339 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
4340 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
4341 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
4342 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
4343 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
4344 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
4345 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
4346 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
Travis Place186c3112008-05-20 11:54:41 +02004347 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004348 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
4349 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
4350 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
Takashi Iwaidea0a502009-02-09 17:14:52 +01004351 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004352 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004353 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
4354 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004355 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
4356 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004357 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
4358 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
4359 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
4360 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004361 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
4362 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004363 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004364 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004365 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004366 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004367 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
4368 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004369 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004370 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004371 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004372 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004373 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
Travis Place1d116042008-06-23 11:42:30 +02004374 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
Daniel T Chen33535412010-04-22 07:15:26 -04004375 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004376 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004377 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004378 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
4379 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004380 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004381 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
4382 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
4383 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
4384 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004385 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
4386 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004387 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004388 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004389 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
4390 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01004391 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
4392 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
4393 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +01004394 /* default Intel */
4395 SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01004396 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
4397 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 {}
4399};
4400
Takashi Iwai16ded522005-06-10 19:58:24 +02004401/*
Kailang Yangdf694da2005-12-05 19:42:22 +01004402 * ALC880 codec presets
Takashi Iwai16ded522005-06-10 19:58:24 +02004403 */
Takashi Iwai16ded522005-06-10 19:58:24 +02004404static struct alc_config_preset alc880_presets[] = {
4405 [ALC880_3ST] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004406 .mixers = { alc880_three_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004407 .init_verbs = { alc880_volume_init_verbs,
4408 alc880_pin_3stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004409 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwai16ded522005-06-10 19:58:24 +02004410 .dac_nids = alc880_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004411 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4412 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004413 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004414 .input_mux = &alc880_capture_source,
4415 },
4416 [ALC880_3ST_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004417 .mixers = { alc880_three_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004418 .init_verbs = { alc880_volume_init_verbs,
4419 alc880_pin_3stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004420 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwai16ded522005-06-10 19:58:24 +02004421 .dac_nids = alc880_dac_nids,
4422 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004423 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4424 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004425 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004426 .input_mux = &alc880_capture_source,
4427 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004428 [ALC880_TCL_S700] = {
4429 .mixers = { alc880_tcl_s700_mixer },
4430 .init_verbs = { alc880_volume_init_verbs,
4431 alc880_pin_tcl_S700_init_verbs,
4432 alc880_gpio2_init_verbs },
4433 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4434 .dac_nids = alc880_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01004435 .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
4436 .num_adc_nids = 1, /* single ADC */
Kailang Yangdf694da2005-12-05 19:42:22 +01004437 .hp_nid = 0x03,
4438 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4439 .channel_mode = alc880_2_jack_modes,
4440 .input_mux = &alc880_capture_source,
4441 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004442 [ALC880_5ST] = {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004443 .mixers = { alc880_three_stack_mixer,
4444 alc880_five_stack_mixer},
4445 .init_verbs = { alc880_volume_init_verbs,
4446 alc880_pin_5stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004447 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4448 .dac_nids = alc880_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004449 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
4450 .channel_mode = alc880_fivestack_modes,
4451 .input_mux = &alc880_capture_source,
4452 },
4453 [ALC880_5ST_DIG] = {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004454 .mixers = { alc880_three_stack_mixer,
4455 alc880_five_stack_mixer },
4456 .init_verbs = { alc880_volume_init_verbs,
4457 alc880_pin_5stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004458 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4459 .dac_nids = alc880_dac_nids,
4460 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004461 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
4462 .channel_mode = alc880_fivestack_modes,
4463 .input_mux = &alc880_capture_source,
4464 },
Takashi Iwaib6482d42005-06-27 15:32:43 +02004465 [ALC880_6ST] = {
4466 .mixers = { alc880_six_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004467 .init_verbs = { alc880_volume_init_verbs,
4468 alc880_pin_6stack_init_verbs },
Takashi Iwaib6482d42005-06-27 15:32:43 +02004469 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
4470 .dac_nids = alc880_6st_dac_nids,
4471 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
4472 .channel_mode = alc880_sixstack_modes,
4473 .input_mux = &alc880_6stack_capture_source,
4474 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004475 [ALC880_6ST_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004476 .mixers = { alc880_six_stack_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004477 .init_verbs = { alc880_volume_init_verbs,
4478 alc880_pin_6stack_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004479 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
4480 .dac_nids = alc880_6st_dac_nids,
4481 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004482 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
4483 .channel_mode = alc880_sixstack_modes,
4484 .input_mux = &alc880_6stack_capture_source,
4485 },
4486 [ALC880_W810] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004487 .mixers = { alc880_w810_base_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004488 .init_verbs = { alc880_volume_init_verbs,
4489 alc880_pin_w810_init_verbs,
Takashi Iwaib0af0de2005-06-21 14:49:19 +02004490 alc880_gpio2_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004491 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
4492 .dac_nids = alc880_w810_dac_nids,
4493 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004494 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
4495 .channel_mode = alc880_w810_modes,
4496 .input_mux = &alc880_capture_source,
4497 },
4498 [ALC880_Z71V] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004499 .mixers = { alc880_z71v_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004500 .init_verbs = { alc880_volume_init_verbs,
4501 alc880_pin_z71v_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004502 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
4503 .dac_nids = alc880_z71v_dac_nids,
4504 .dig_out_nid = ALC880_DIGOUT_NID,
4505 .hp_nid = 0x03,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004506 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4507 .channel_mode = alc880_2_jack_modes,
Takashi Iwai16ded522005-06-10 19:58:24 +02004508 .input_mux = &alc880_capture_source,
4509 },
4510 [ALC880_F1734] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004511 .mixers = { alc880_f1734_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004512 .init_verbs = { alc880_volume_init_verbs,
4513 alc880_pin_f1734_init_verbs },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004514 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
4515 .dac_nids = alc880_f1734_dac_nids,
4516 .hp_nid = 0x02,
4517 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4518 .channel_mode = alc880_2_jack_modes,
Takashi Iwai937b4162008-02-11 14:52:36 +01004519 .input_mux = &alc880_f1734_capture_source,
4520 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004521 .setup = alc880_uniwill_p53_setup,
4522 .init_hook = alc_automute_amp,
Takashi Iwai16ded522005-06-10 19:58:24 +02004523 },
4524 [ALC880_ASUS] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004525 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004526 .init_verbs = { alc880_volume_init_verbs,
4527 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004528 alc880_gpio1_init_verbs },
4529 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4530 .dac_nids = alc880_asus_dac_nids,
4531 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4532 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004533 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004534 .input_mux = &alc880_capture_source,
4535 },
4536 [ALC880_ASUS_DIG] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004537 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004538 .init_verbs = { alc880_volume_init_verbs,
4539 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004540 alc880_gpio1_init_verbs },
4541 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4542 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004543 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004544 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4545 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004546 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004547 .input_mux = &alc880_capture_source,
4548 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004549 [ALC880_ASUS_DIG2] = {
4550 .mixers = { alc880_asus_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004551 .init_verbs = { alc880_volume_init_verbs,
4552 alc880_pin_asus_init_verbs,
Kailang Yangdf694da2005-12-05 19:42:22 +01004553 alc880_gpio2_init_verbs }, /* use GPIO2 */
4554 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4555 .dac_nids = alc880_asus_dac_nids,
4556 .dig_out_nid = ALC880_DIGOUT_NID,
4557 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4558 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004559 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +01004560 .input_mux = &alc880_capture_source,
4561 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004562 [ALC880_ASUS_W1V] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004563 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004564 .init_verbs = { alc880_volume_init_verbs,
4565 alc880_pin_asus_init_verbs,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004566 alc880_gpio1_init_verbs },
4567 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4568 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004569 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004570 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4571 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004572 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004573 .input_mux = &alc880_capture_source,
4574 },
4575 [ALC880_UNIWILL_DIG] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01004576 .mixers = { alc880_asus_mixer },
Kailang Yangccc656c2006-10-17 12:32:26 +02004577 .init_verbs = { alc880_volume_init_verbs,
4578 alc880_pin_asus_init_verbs },
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004579 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4580 .dac_nids = alc880_asus_dac_nids,
Takashi Iwai16ded522005-06-10 19:58:24 +02004581 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004582 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
4583 .channel_mode = alc880_asus_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004584 .need_dac_fix = 1,
Takashi Iwai16ded522005-06-10 19:58:24 +02004585 .input_mux = &alc880_capture_source,
4586 },
Kailang Yangccc656c2006-10-17 12:32:26 +02004587 [ALC880_UNIWILL] = {
4588 .mixers = { alc880_uniwill_mixer },
4589 .init_verbs = { alc880_volume_init_verbs,
4590 alc880_uniwill_init_verbs },
4591 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4592 .dac_nids = alc880_asus_dac_nids,
4593 .dig_out_nid = ALC880_DIGOUT_NID,
4594 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4595 .channel_mode = alc880_threestack_modes,
4596 .need_dac_fix = 1,
4597 .input_mux = &alc880_capture_source,
4598 .unsol_event = alc880_uniwill_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004599 .setup = alc880_uniwill_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004600 .init_hook = alc880_uniwill_init_hook,
Kailang Yangccc656c2006-10-17 12:32:26 +02004601 },
4602 [ALC880_UNIWILL_P53] = {
4603 .mixers = { alc880_uniwill_p53_mixer },
4604 .init_verbs = { alc880_volume_init_verbs,
4605 alc880_uniwill_p53_init_verbs },
4606 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
4607 .dac_nids = alc880_asus_dac_nids,
4608 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004609 .channel_mode = alc880_threestack_modes,
4610 .input_mux = &alc880_capture_source,
4611 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004612 .setup = alc880_uniwill_p53_setup,
4613 .init_hook = alc_automute_amp,
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004614 },
4615 [ALC880_FUJITSU] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01004616 .mixers = { alc880_fujitsu_mixer },
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004617 .init_verbs = { alc880_volume_init_verbs,
4618 alc880_uniwill_p53_init_verbs,
4619 alc880_beep_init_verbs },
4620 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4621 .dac_nids = alc880_dac_nids,
Takashi Iwaid53d7d92007-08-20 15:20:02 +02004622 .dig_out_nid = ALC880_DIGOUT_NID,
Tobin Davis2cf9f0f2007-02-07 16:04:25 +01004623 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4624 .channel_mode = alc880_2_jack_modes,
Kailang Yangccc656c2006-10-17 12:32:26 +02004625 .input_mux = &alc880_capture_source,
4626 .unsol_event = alc880_uniwill_p53_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004627 .setup = alc880_uniwill_p53_setup,
4628 .init_hook = alc_automute_amp,
Kailang Yangccc656c2006-10-17 12:32:26 +02004629 },
Kailang Yangdf694da2005-12-05 19:42:22 +01004630 [ALC880_CLEVO] = {
4631 .mixers = { alc880_three_stack_mixer },
4632 .init_verbs = { alc880_volume_init_verbs,
4633 alc880_pin_clevo_init_verbs },
4634 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4635 .dac_nids = alc880_dac_nids,
4636 .hp_nid = 0x03,
4637 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
4638 .channel_mode = alc880_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004639 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +01004640 .input_mux = &alc880_capture_source,
4641 },
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004642 [ALC880_LG] = {
4643 .mixers = { alc880_lg_mixer },
4644 .init_verbs = { alc880_volume_init_verbs,
4645 alc880_lg_init_verbs },
4646 .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
4647 .dac_nids = alc880_lg_dac_nids,
4648 .dig_out_nid = ALC880_DIGOUT_NID,
4649 .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
4650 .channel_mode = alc880_lg_ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02004651 .need_dac_fix = 1,
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004652 .input_mux = &alc880_lg_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004653 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004654 .setup = alc880_lg_setup,
4655 .init_hook = alc_automute_amp,
Takashi Iwaicb53c622007-08-10 17:21:45 +02004656#ifdef CONFIG_SND_HDA_POWER_SAVE
4657 .loopbacks = alc880_lg_loopbacks,
4658#endif
Takashi Iwaiae6b8132006-03-03 16:47:17 +01004659 },
Takashi Iwaid6815182006-03-23 16:06:23 +01004660 [ALC880_LG_LW] = {
4661 .mixers = { alc880_lg_lw_mixer },
4662 .init_verbs = { alc880_volume_init_verbs,
4663 alc880_lg_lw_init_verbs },
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02004664 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
Takashi Iwaid6815182006-03-23 16:06:23 +01004665 .dac_nids = alc880_dac_nids,
4666 .dig_out_nid = ALC880_DIGOUT_NID,
Claudio Matsuoka0a8c5da2007-07-04 15:17:38 +02004667 .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
4668 .channel_mode = alc880_lg_lw_modes,
Takashi Iwaid6815182006-03-23 16:06:23 +01004669 .input_mux = &alc880_lg_lw_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02004670 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004671 .setup = alc880_lg_lw_setup,
4672 .init_hook = alc_automute_amp,
Takashi Iwaid6815182006-03-23 16:06:23 +01004673 },
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004674 [ALC880_MEDION_RIM] = {
4675 .mixers = { alc880_medion_rim_mixer },
4676 .init_verbs = { alc880_volume_init_verbs,
4677 alc880_medion_rim_init_verbs,
4678 alc_gpio2_init_verbs },
4679 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
4680 .dac_nids = alc880_dac_nids,
4681 .dig_out_nid = ALC880_DIGOUT_NID,
4682 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
4683 .channel_mode = alc880_2_jack_modes,
4684 .input_mux = &alc880_medion_rim_capture_source,
4685 .unsol_event = alc880_medion_rim_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02004686 .setup = alc880_medion_rim_setup,
4687 .init_hook = alc880_medion_rim_automute,
Takashi Iwaidf99cd32008-04-25 15:25:04 +02004688 },
Takashi Iwai16ded522005-06-10 19:58:24 +02004689#ifdef CONFIG_SND_DEBUG
4690 [ALC880_TEST] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004691 .mixers = { alc880_test_mixer },
4692 .init_verbs = { alc880_test_init_verbs },
Takashi Iwai16ded522005-06-10 19:58:24 +02004693 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
4694 .dac_nids = alc880_test_dac_nids,
4695 .dig_out_nid = ALC880_DIGOUT_NID,
Takashi Iwai16ded522005-06-10 19:58:24 +02004696 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
4697 .channel_mode = alc880_test_modes,
4698 .input_mux = &alc880_test_capture_source,
4699 },
4700#endif
4701};
4702
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004703/*
4704 * Automatic parse of I/O pins from the BIOS configuration
4705 */
4706
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004707enum {
4708 ALC_CTL_WIDGET_VOL,
4709 ALC_CTL_WIDGET_MUTE,
4710 ALC_CTL_BIND_MUTE,
4711};
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01004712static struct snd_kcontrol_new alc880_control_templates[] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004713 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
4714 HDA_CODEC_MUTE(NULL, 0, 0, 0),
Takashi Iwai985be542005-11-02 18:26:49 +01004715 HDA_BIND_MUTE(NULL, 0, 0, 0),
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004716};
4717
4718/* add dynamic controls */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004719static int add_control(struct alc_spec *spec, int type, const char *name,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004720 int cidx, unsigned long val)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004721{
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01004722 struct snd_kcontrol_new *knew;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004723
Takashi Iwai603c4012008-07-30 15:01:44 +02004724 snd_array_init(&spec->kctls, sizeof(*knew), 32);
4725 knew = snd_array_new(&spec->kctls);
4726 if (!knew)
4727 return -ENOMEM;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004728 *knew = alc880_control_templates[type];
Paulo Marques543537b2005-06-23 00:09:02 -07004729 knew->name = kstrdup(name, GFP_KERNEL);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004730 if (!knew->name)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004731 return -ENOMEM;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004732 knew->index = cidx;
Jaroslav Kysela4d02d1b2009-11-12 10:15:48 +01004733 if (get_amp_nid_(val))
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +01004734 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004735 knew->private_value = val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004736 return 0;
4737}
4738
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004739static int add_control_with_pfx(struct alc_spec *spec, int type,
4740 const char *pfx, const char *dir,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004741 const char *sfx, int cidx, unsigned long val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004742{
4743 char name[32];
4744 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004745 return add_control(spec, type, name, cidx, val);
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004746}
4747
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004748#define add_pb_vol_ctrl(spec, type, pfx, val) \
4749 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
4750#define add_pb_sw_ctrl(spec, type, pfx, val) \
4751 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
4752#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
4753 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
4754#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
4755 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004756
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004757#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
4758#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
4759#define alc880_is_multi_pin(nid) ((nid) >= 0x18)
4760#define alc880_multi_pin_idx(nid) ((nid) - 0x18)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004761#define alc880_idx_to_dac(nid) ((nid) + 0x02)
4762#define alc880_dac_to_idx(nid) ((nid) - 0x02)
4763#define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
4764#define alc880_idx_to_selector(nid) ((nid) + 0x10)
4765#define ALC880_PIN_CD_NID 0x1c
4766
4767/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004768static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
4769 const struct auto_pin_cfg *cfg)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004770{
4771 hda_nid_t nid;
4772 int assigned[4];
4773 int i, j;
4774
4775 memset(assigned, 0, sizeof(assigned));
Takashi Iwaib0af0de2005-06-21 14:49:19 +02004776 spec->multiout.dac_nids = spec->private_dac_nids;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004777
4778 /* check the pins hardwired to audio widget */
4779 for (i = 0; i < cfg->line_outs; i++) {
4780 nid = cfg->line_out_pins[i];
4781 if (alc880_is_fixed_pin(nid)) {
4782 int idx = alc880_fixed_pin_idx(nid);
Libin Yang5014f192005-11-23 15:48:36 +01004783 spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004784 assigned[idx] = 1;
4785 }
4786 }
4787 /* left pins can be connect to any audio widget */
4788 for (i = 0; i < cfg->line_outs; i++) {
4789 nid = cfg->line_out_pins[i];
4790 if (alc880_is_fixed_pin(nid))
4791 continue;
4792 /* search for an empty channel */
4793 for (j = 0; j < cfg->line_outs; j++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004794 if (!assigned[j]) {
4795 spec->multiout.dac_nids[i] =
4796 alc880_idx_to_dac(j);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004797 assigned[j] = 1;
4798 break;
4799 }
4800 }
4801 }
4802 spec->multiout.num_dacs = cfg->line_outs;
4803 return 0;
4804}
4805
4806/* add playback controls from the parsed DAC table */
Kailang Yangdf694da2005-12-05 19:42:22 +01004807static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
4808 const struct auto_pin_cfg *cfg)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004809{
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004810 static const char *chname[4] = {
4811 "Front", "Surround", NULL /*CLFE*/, "Side"
4812 };
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004813 hda_nid_t nid;
4814 int i, err;
4815
4816 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004817 if (!spec->multiout.dac_nids[i])
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004818 continue;
4819 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
4820 if (i == 2) {
4821 /* Center/LFE */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004822 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
4823 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004824 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
4825 HDA_OUTPUT));
4826 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004827 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004828 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
4829 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004830 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
4831 HDA_OUTPUT));
4832 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004833 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004834 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
4835 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004836 HDA_COMPOSE_AMP_VAL(nid, 1, 2,
4837 HDA_INPUT));
4838 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004839 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004840 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
4841 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004842 HDA_COMPOSE_AMP_VAL(nid, 2, 2,
4843 HDA_INPUT));
4844 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004845 return err;
4846 } else {
Takashi Iwaicb162b62009-08-25 16:05:03 +02004847 const char *pfx;
4848 if (cfg->line_outs == 1 &&
4849 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
4850 pfx = "Speaker";
4851 else
4852 pfx = chname[i];
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004853 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004854 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
4855 HDA_OUTPUT));
4856 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004857 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004858 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004859 HDA_COMPOSE_AMP_VAL(nid, 3, 2,
4860 HDA_INPUT));
4861 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004862 return err;
4863 }
4864 }
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004865 return 0;
4866}
4867
Takashi Iwai8d88bc32005-11-17 11:09:23 +01004868/* add playback controls for speaker and HP outputs */
4869static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
4870 const char *pfx)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004871{
4872 hda_nid_t nid;
4873 int err;
4874
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004875 if (!pin)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004876 return 0;
4877
4878 if (alc880_is_fixed_pin(pin)) {
4879 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
Takashi Iwai82bc9552006-03-21 11:24:42 +01004880 /* specify the DAC as the extra output */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004881 if (!spec->multiout.hp_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004882 spec->multiout.hp_nid = nid;
Takashi Iwai82bc9552006-03-21 11:24:42 +01004883 else
4884 spec->multiout.extra_out_nid[0] = nid;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004885 /* control HP volume/switch on the output mixer amp */
4886 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004887 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004888 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
4889 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004890 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004891 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004892 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
4893 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004894 return err;
4895 } else if (alc880_is_multi_pin(pin)) {
4896 /* set manual connection */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004897 /* we have only a switch on HP-out PIN */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02004898 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004899 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
4900 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004901 return err;
4902 }
4903 return 0;
4904}
4905
4906/* create input playback/capture controls for the given pin */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004907static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004908 const char *ctlname, int ctlidx,
Kailang Yangdf694da2005-12-05 19:42:22 +01004909 int idx, hda_nid_t mix_nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004910{
Kailang Yangdf694da2005-12-05 19:42:22 +01004911 int err;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004912
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004913 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004914 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4915 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004916 return err;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004917 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004918 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4919 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004920 return err;
4921 return 0;
4922}
4923
Takashi Iwai05f5f472009-08-25 13:10:18 +02004924static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004925{
Takashi Iwai05f5f472009-08-25 13:10:18 +02004926 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
4927 return (pincap & AC_PINCAP_IN) != 0;
4928}
4929
4930/* create playback/capture controls for input pins */
4931static int alc_auto_create_input_ctls(struct hda_codec *codec,
4932 const struct auto_pin_cfg *cfg,
4933 hda_nid_t mixer,
4934 hda_nid_t cap1, hda_nid_t cap2)
4935{
4936 struct alc_spec *spec = codec->spec;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02004937 struct hda_input_mux *imux = &spec->private_imux[0];
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004938 int i, err, idx, type, type_idx = 0;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004939
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004940 for (i = 0; i < cfg->num_inputs; i++) {
Takashi Iwai05f5f472009-08-25 13:10:18 +02004941 hda_nid_t pin;
4942
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004943 pin = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02004944 if (!alc_is_input_pin(codec, pin))
4945 continue;
4946
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004947 type = cfg->inputs[i].type;
4948 if (i > 0 && type == cfg->inputs[i - 1].type)
4949 type_idx++;
4950 else
4951 type_idx = 0;
Takashi Iwai05f5f472009-08-25 13:10:18 +02004952 if (mixer) {
4953 idx = get_connection_index(codec, mixer, pin);
4954 if (idx >= 0) {
4955 err = new_analog_input(spec, pin,
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004956 auto_pin_cfg_labels[type],
4957 type_idx, idx, mixer);
Takashi Iwai05f5f472009-08-25 13:10:18 +02004958 if (err < 0)
4959 return err;
4960 }
4961 }
4962
4963 if (!cap1)
4964 continue;
4965 idx = get_connection_index(codec, cap1, pin);
4966 if (idx < 0 && cap2)
4967 idx = get_connection_index(codec, cap2, pin);
4968 if (idx >= 0) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02004969 imux->items[imux->num_items].label =
Takashi Iwai66ceeb62010-08-30 13:05:52 +02004970 snd_hda_get_input_pin_label(cfg, i);
Takashi Iwai05f5f472009-08-25 13:10:18 +02004971 imux->items[imux->num_items].index = idx;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004972 imux->num_items++;
4973 }
4974 }
4975 return 0;
4976}
4977
Takashi Iwai05f5f472009-08-25 13:10:18 +02004978static int alc880_auto_create_input_ctls(struct hda_codec *codec,
4979 const struct auto_pin_cfg *cfg)
4980{
4981 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x08, 0x09);
4982}
4983
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004984static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
4985 unsigned int pin_type)
4986{
4987 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4988 pin_type);
4989 /* unmute pin */
Takashi Iwaid260cdf2008-02-13 17:19:35 +01004990 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4991 AMP_OUT_UNMUTE);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004992}
4993
Kailang Yangdf694da2005-12-05 19:42:22 +01004994static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
4995 hda_nid_t nid, int pin_type,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004996 int dac_idx)
4997{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01004998 alc_set_pin_output(codec, nid, pin_type);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02004999 /* need the manual connection? */
5000 if (alc880_is_multi_pin(nid)) {
5001 struct alc_spec *spec = codec->spec;
5002 int idx = alc880_multi_pin_idx(nid);
5003 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
5004 AC_VERB_SET_CONNECT_SEL,
5005 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
5006 }
5007}
5008
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02005009static int get_pin_type(int line_out_type)
5010{
5011 if (line_out_type == AUTO_PIN_HP_OUT)
5012 return PIN_HP;
5013 else
5014 return PIN_OUT;
5015}
5016
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005017static void alc880_auto_init_multi_out(struct hda_codec *codec)
5018{
5019 struct alc_spec *spec = codec->spec;
5020 int i;
Kailang Yangea1fb292008-08-26 12:58:38 +02005021
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005022 for (i = 0; i < spec->autocfg.line_outs; i++) {
5023 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02005024 int pin_type = get_pin_type(spec->autocfg.line_out_type);
5025 alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005026 }
5027}
5028
Takashi Iwai8d88bc32005-11-17 11:09:23 +01005029static void alc880_auto_init_extra_out(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005030{
5031 struct alc_spec *spec = codec->spec;
5032 hda_nid_t pin;
5033
Takashi Iwai82bc9552006-03-21 11:24:42 +01005034 pin = spec->autocfg.speaker_pins[0];
Takashi Iwai8d88bc32005-11-17 11:09:23 +01005035 if (pin) /* connect to front */
5036 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
Takashi Iwaieb06ed82006-09-20 17:10:27 +02005037 pin = spec->autocfg.hp_pins[0];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005038 if (pin) /* connect to front */
5039 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
5040}
5041
5042static void alc880_auto_init_analog_input(struct hda_codec *codec)
5043{
5044 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02005045 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005046 int i;
5047
Takashi Iwai66ceeb62010-08-30 13:05:52 +02005048 for (i = 0; i < cfg->num_inputs; i++) {
5049 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +02005050 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +01005051 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +01005052 if (nid != ALC880_PIN_CD_NID &&
5053 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005054 snd_hda_codec_write(codec, nid, 0,
5055 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005056 AMP_OUT_MUTE);
5057 }
5058 }
5059}
5060
Takashi Iwai7f311a42010-04-09 17:32:23 +02005061static void alc880_auto_init_input_src(struct hda_codec *codec)
5062{
5063 struct alc_spec *spec = codec->spec;
5064 int c;
5065
5066 for (c = 0; c < spec->num_adc_nids; c++) {
5067 unsigned int mux_idx;
5068 const struct hda_input_mux *imux;
5069 mux_idx = c >= spec->num_mux_defs ? 0 : c;
5070 imux = &spec->input_mux[mux_idx];
5071 if (!imux->num_items && mux_idx > 0)
5072 imux = &spec->input_mux[0];
5073 if (imux)
5074 snd_hda_codec_write(codec, spec->adc_nids[c], 0,
5075 AC_VERB_SET_CONNECT_SEL,
5076 imux->items[0].index);
5077 }
5078}
5079
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005080/* parse the BIOS configuration and set up the alc_spec */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005081/* return 1 if successful, 0 if the proper config is not found,
5082 * or a negative error code
5083 */
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005084static int alc880_parse_auto_config(struct hda_codec *codec)
5085{
5086 struct alc_spec *spec = codec->spec;
Takashi Iwai757899a2010-07-30 10:48:14 +02005087 int err;
Kailang Yangdf694da2005-12-05 19:42:22 +01005088 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005089
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005090 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
5091 alc880_ignore);
5092 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005093 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005094 if (!spec->autocfg.line_outs)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005095 return 0; /* can't find valid BIOS pin config */
Kailang Yangdf694da2005-12-05 19:42:22 +01005096
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005097 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
5098 if (err < 0)
5099 return err;
5100 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
5101 if (err < 0)
5102 return err;
5103 err = alc880_auto_create_extra_out(spec,
5104 spec->autocfg.speaker_pins[0],
5105 "Speaker");
5106 if (err < 0)
5107 return err;
5108 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
5109 "Headphone");
5110 if (err < 0)
5111 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +02005112 err = alc880_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005113 if (err < 0)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005114 return err;
5115
5116 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
5117
Takashi Iwai757899a2010-07-30 10:48:14 +02005118 alc_auto_parse_digital(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005119
Takashi Iwai603c4012008-07-30 15:01:44 +02005120 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +01005121 add_mixer(spec, spec->kctls.list);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005122
Takashi Iwaid88897e2008-10-31 15:01:37 +01005123 add_verb(spec, alc880_volume_init_verbs);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005124
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005125 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02005126 spec->input_mux = &spec->private_imux[0];
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005127
Kailang Yang6227cdc2010-02-25 08:36:52 +01005128 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02005129
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005130 return 1;
5131}
5132
Takashi Iwaiae6b8132006-03-03 16:47:17 +01005133/* additional initialization for auto-configuration model */
5134static void alc880_auto_init(struct hda_codec *codec)
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005135{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01005136 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005137 alc880_auto_init_multi_out(codec);
Takashi Iwai8d88bc32005-11-17 11:09:23 +01005138 alc880_auto_init_extra_out(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005139 alc880_auto_init_analog_input(codec);
Takashi Iwai7f311a42010-04-09 17:32:23 +02005140 alc880_auto_init_input_src(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +02005141 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01005142 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +02005143 alc_inithook(codec);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005144}
5145
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005146/* check the ADC/MUX contains all input pins; some ADC/MUX contains only
5147 * one of two digital mic pins, e.g. on ALC272
5148 */
5149static void fixup_automic_adc(struct hda_codec *codec)
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005150{
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005151 struct alc_spec *spec = codec->spec;
5152 int i;
5153
5154 for (i = 0; i < spec->num_adc_nids; i++) {
5155 hda_nid_t cap = spec->capsrc_nids ?
5156 spec->capsrc_nids[i] : spec->adc_nids[i];
5157 int iidx, eidx;
5158
5159 iidx = get_connection_index(codec, cap, spec->int_mic.pin);
5160 if (iidx < 0)
5161 continue;
5162 eidx = get_connection_index(codec, cap, spec->ext_mic.pin);
5163 if (eidx < 0)
5164 continue;
5165 spec->int_mic.mux_idx = iidx;
5166 spec->ext_mic.mux_idx = eidx;
5167 if (spec->capsrc_nids)
5168 spec->capsrc_nids += i;
5169 spec->adc_nids += i;
5170 spec->num_adc_nids = 1;
5171 return;
5172 }
5173 snd_printd(KERN_INFO "hda_codec: %s: "
5174 "No ADC/MUX containing both 0x%x and 0x%x pins\n",
5175 codec->chip_name, spec->int_mic.pin, spec->ext_mic.pin);
5176 spec->auto_mic = 0; /* disable auto-mic to be sure */
5177}
5178
Takashi Iwai748cce42010-08-04 07:37:39 +02005179/* select or unmute the given capsrc route */
5180static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
5181 int idx)
5182{
5183 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
5184 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
5185 HDA_AMP_MUTE, 0);
5186 } else {
5187 snd_hda_codec_write_cache(codec, cap, 0,
5188 AC_VERB_SET_CONNECT_SEL, idx);
5189 }
5190}
5191
Takashi Iwai840b64c2010-07-13 22:49:01 +02005192/* set the default connection to that pin */
5193static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
5194{
5195 struct alc_spec *spec = codec->spec;
5196 int i;
5197
5198 for (i = 0; i < spec->num_adc_nids; i++) {
5199 hda_nid_t cap = spec->capsrc_nids ?
5200 spec->capsrc_nids[i] : spec->adc_nids[i];
5201 int idx;
5202
5203 idx = get_connection_index(codec, cap, pin);
5204 if (idx < 0)
5205 continue;
Takashi Iwai748cce42010-08-04 07:37:39 +02005206 select_or_unmute_capsrc(codec, cap, idx);
Takashi Iwai840b64c2010-07-13 22:49:01 +02005207 return i; /* return the found index */
5208 }
5209 return -1; /* not found */
5210}
5211
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005212/* choose the ADC/MUX containing the input pin and initialize the setup */
5213static void fixup_single_adc(struct hda_codec *codec)
5214{
5215 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02005216 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005217 int i;
5218
5219 /* search for the input pin; there must be only one */
Takashi Iwai66ceeb62010-08-30 13:05:52 +02005220 if (cfg->num_inputs != 1)
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005221 return;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02005222 i = init_capsrc_for_pin(codec, cfg->inputs[0].pin);
Takashi Iwai840b64c2010-07-13 22:49:01 +02005223 if (i >= 0) {
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005224 /* use only this ADC */
5225 if (spec->capsrc_nids)
5226 spec->capsrc_nids += i;
5227 spec->adc_nids += i;
5228 spec->num_adc_nids = 1;
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005229 }
5230}
5231
Takashi Iwai840b64c2010-07-13 22:49:01 +02005232/* initialize dual adcs */
5233static void fixup_dual_adc_switch(struct hda_codec *codec)
5234{
5235 struct alc_spec *spec = codec->spec;
5236 init_capsrc_for_pin(codec, spec->ext_mic.pin);
5237 init_capsrc_for_pin(codec, spec->int_mic.pin);
5238}
5239
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005240static void set_capture_mixer(struct hda_codec *codec)
5241{
5242 struct alc_spec *spec = codec->spec;
Takashi Iwaia23b6882009-03-23 15:21:36 +01005243 static struct snd_kcontrol_new *caps[2][3] = {
5244 { alc_capture_mixer_nosrc1,
5245 alc_capture_mixer_nosrc2,
5246 alc_capture_mixer_nosrc3 },
5247 { alc_capture_mixer1,
5248 alc_capture_mixer2,
5249 alc_capture_mixer3 },
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005250 };
Takashi Iwaia23b6882009-03-23 15:21:36 +01005251 if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005252 int mux = 0;
Takashi Iwai840b64c2010-07-13 22:49:01 +02005253 int num_adcs = spec->num_adc_nids;
5254 if (spec->dual_adc_switch)
5255 fixup_dual_adc_switch(codec);
5256 else if (spec->auto_mic)
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005257 fixup_automic_adc(codec);
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +01005258 else if (spec->input_mux) {
5259 if (spec->input_mux->num_items > 1)
5260 mux = 1;
5261 else if (spec->input_mux->num_items == 1)
5262 fixup_single_adc(codec);
5263 }
Takashi Iwai840b64c2010-07-13 22:49:01 +02005264 if (spec->dual_adc_switch)
5265 num_adcs = 1;
5266 spec->cap_mixer = caps[mux][num_adcs - 1];
Takashi Iwaia23b6882009-03-23 15:21:36 +01005267 }
Takashi Iwaif9e336f2008-10-31 16:37:07 +01005268}
5269
Takashi Iwai66946352010-03-29 17:21:45 +02005270/* fill adc_nids (and capsrc_nids) containing all active input pins */
5271static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
5272 int num_nids)
5273{
5274 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02005275 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai66946352010-03-29 17:21:45 +02005276 int n;
5277 hda_nid_t fallback_adc = 0, fallback_cap = 0;
5278
5279 for (n = 0; n < num_nids; n++) {
5280 hda_nid_t adc, cap;
5281 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
5282 int nconns, i, j;
5283
5284 adc = nids[n];
5285 if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN)
5286 continue;
5287 cap = adc;
5288 nconns = snd_hda_get_connections(codec, cap, conn,
5289 ARRAY_SIZE(conn));
5290 if (nconns == 1) {
5291 cap = conn[0];
5292 nconns = snd_hda_get_connections(codec, cap, conn,
5293 ARRAY_SIZE(conn));
5294 }
5295 if (nconns <= 0)
5296 continue;
5297 if (!fallback_adc) {
5298 fallback_adc = adc;
5299 fallback_cap = cap;
5300 }
Takashi Iwai66ceeb62010-08-30 13:05:52 +02005301 for (i = 0; i < cfg->num_inputs; i++) {
5302 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai66946352010-03-29 17:21:45 +02005303 for (j = 0; j < nconns; j++) {
5304 if (conn[j] == nid)
5305 break;
5306 }
5307 if (j >= nconns)
5308 break;
5309 }
Takashi Iwai66ceeb62010-08-30 13:05:52 +02005310 if (i >= cfg->num_inputs) {
Takashi Iwai66946352010-03-29 17:21:45 +02005311 int num_adcs = spec->num_adc_nids;
5312 spec->private_adc_nids[num_adcs] = adc;
5313 spec->private_capsrc_nids[num_adcs] = cap;
5314 spec->num_adc_nids++;
5315 spec->adc_nids = spec->private_adc_nids;
5316 if (adc != cap)
5317 spec->capsrc_nids = spec->private_capsrc_nids;
5318 }
5319 }
5320 if (!spec->num_adc_nids) {
5321 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
Takashi Iwai1f85d722010-03-30 07:48:05 +02005322 " using fallback 0x%x\n",
5323 codec->chip_name, fallback_adc);
Takashi Iwai66946352010-03-29 17:21:45 +02005324 spec->private_adc_nids[0] = fallback_adc;
5325 spec->adc_nids = spec->private_adc_nids;
5326 if (fallback_adc != fallback_cap) {
5327 spec->private_capsrc_nids[0] = fallback_cap;
5328 spec->capsrc_nids = spec->private_adc_nids;
5329 }
5330 }
5331}
5332
Takashi Iwai67d634c2009-11-16 15:35:59 +01005333#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01005334#define set_beep_amp(spec, nid, idx, dir) \
5335 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
Takashi Iwaidc1eae22010-07-29 15:30:02 +02005336
5337static struct snd_pci_quirk beep_white_list[] = {
5338 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
Takashi Iwaie096c8e2010-08-03 17:20:35 +02005339 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
Takashi Iwaidc1eae22010-07-29 15:30:02 +02005340 {}
5341};
5342
5343static inline int has_cdefine_beep(struct hda_codec *codec)
5344{
5345 struct alc_spec *spec = codec->spec;
5346 const struct snd_pci_quirk *q;
5347 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
5348 if (q)
5349 return q->value;
5350 return spec->cdefine.enable_pcbeep;
5351}
Takashi Iwai67d634c2009-11-16 15:35:59 +01005352#else
5353#define set_beep_amp(spec, nid, idx, dir) /* NOP */
Takashi Iwaidc1eae22010-07-29 15:30:02 +02005354#define has_cdefine_beep(codec) 0
Takashi Iwai67d634c2009-11-16 15:35:59 +01005355#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01005356
5357/*
5358 * OK, here we have finally the patch for ALC880
5359 */
5360
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361static int patch_alc880(struct hda_codec *codec)
5362{
5363 struct alc_spec *spec;
5364 int board_config;
Kailang Yangdf694da2005-12-05 19:42:22 +01005365 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366
Takashi Iwaie560d8d2005-09-09 14:21:46 +02005367 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368 if (spec == NULL)
5369 return -ENOMEM;
5370
5371 codec->spec = spec;
5372
Takashi Iwaif5fcc132006-11-24 17:07:44 +01005373 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
5374 alc880_models,
5375 alc880_cfg_tbl);
5376 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02005377 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5378 codec->chip_name);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005379 board_config = ALC880_AUTO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005380 }
5381
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005382 if (board_config == ALC880_AUTO) {
5383 /* automatic parse from the BIOS config */
5384 err = alc880_parse_auto_config(codec);
5385 if (err < 0) {
5386 alc_free(codec);
5387 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005388 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02005389 printk(KERN_INFO
5390 "hda_codec: Cannot set up configuration "
5391 "from BIOS. Using 3-stack mode...\n");
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005392 board_config = ALC880_3ST;
5393 }
5394 }
5395
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09005396 err = snd_hda_attach_beep_device(codec, 0x1);
5397 if (err < 0) {
5398 alc_free(codec);
5399 return err;
5400 }
5401
Kailang Yangdf694da2005-12-05 19:42:22 +01005402 if (board_config != ALC880_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02005403 setup_preset(codec, &alc880_presets[board_config]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405 spec->stream_analog_playback = &alc880_pcm_analog_playback;
5406 spec->stream_analog_capture = &alc880_pcm_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +01005407 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409 spec->stream_digital_playback = &alc880_pcm_digital_playback;
5410 spec->stream_digital_capture = &alc880_pcm_digital_capture;
5411
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005412 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005413 /* check whether NID 0x07 is valid */
Takashi Iwai54d17402005-11-21 16:33:22 +01005414 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005415 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +02005416 wcap = get_wcaps_type(wcap);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005417 if (wcap != AC_WID_AUD_IN) {
5418 spec->adc_nids = alc880_adc_nids_alt;
5419 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005420 } else {
5421 spec->adc_nids = alc880_adc_nids;
5422 spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005423 }
5424 }
Takashi Iwaib59bdf32009-08-11 09:47:30 +02005425 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01005426 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427
Takashi Iwai2134ea42008-01-10 16:53:55 +01005428 spec->vmaster_nid = 0x0c;
5429
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430 codec->patch_ops = alc_patch_ops;
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005431 if (board_config == ALC880_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01005432 spec->init_hook = alc880_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +02005433#ifdef CONFIG_SND_HDA_POWER_SAVE
5434 if (!spec->loopback.amplist)
5435 spec->loopback.amplist = alc880_loopbacks;
5436#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437
5438 return 0;
5439}
5440
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005441
Linus Torvalds1da177e2005-04-16 15:20:36 -07005442/*
5443 * ALC260 support
5444 */
5445
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005446static hda_nid_t alc260_dac_nids[1] = {
5447 /* front */
5448 0x02,
5449};
5450
5451static hda_nid_t alc260_adc_nids[1] = {
5452 /* ADC0 */
5453 0x04,
5454};
5455
Kailang Yangdf694da2005-12-05 19:42:22 +01005456static hda_nid_t alc260_adc_nids_alt[1] = {
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005457 /* ADC1 */
5458 0x05,
5459};
5460
Jonathan Woithed57fdac2006-02-28 11:38:35 +01005461/* NIDs used when simultaneous access to both ADCs makes sense. Note that
5462 * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
5463 */
5464static hda_nid_t alc260_dual_adc_nids[2] = {
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005465 /* ADC0, ADC1 */
5466 0x04, 0x05
5467};
5468
Takashi Iwaie9edcee2005-06-13 14:16:38 +02005469#define ALC260_DIGOUT_NID 0x03
5470#define ALC260_DIGIN_NID 0x06
5471
5472static struct hda_input_mux alc260_capture_source = {
5473 .num_items = 4,
5474 .items = {
5475 { "Mic", 0x0 },
5476 { "Front Mic", 0x1 },
5477 { "Line", 0x2 },
5478 { "CD", 0x4 },
5479 },
5480};
5481
Jonathan Woithe17e7aec2006-02-28 11:35:18 +01005482/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005483 * headphone jack and the internal CD lines since these are the only pins at
5484 * which audio can appear. For flexibility, also allow the option of
5485 * recording the mixer output on the second ADC (ADC0 doesn't have a
5486 * connection to the mixer output).
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005487 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005488static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
5489 {
5490 .num_items = 3,
5491 .items = {
5492 { "Mic/Line", 0x0 },
5493 { "CD", 0x4 },
5494 { "Headphone", 0x2 },
5495 },
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005496 },
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005497 {
5498 .num_items = 4,
5499 .items = {
5500 { "Mic/Line", 0x0 },
5501 { "CD", 0x4 },
5502 { "Headphone", 0x2 },
5503 { "Mixer", 0x5 },
5504 },
5505 },
5506
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005507};
5508
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005509/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
5510 * the Fujitsu S702x, but jacks are marked differently.
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005511 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005512static struct hda_input_mux alc260_acer_capture_sources[2] = {
5513 {
5514 .num_items = 4,
5515 .items = {
5516 { "Mic", 0x0 },
5517 { "Line", 0x2 },
5518 { "CD", 0x4 },
5519 { "Headphone", 0x5 },
5520 },
5521 },
5522 {
5523 .num_items = 5,
5524 .items = {
5525 { "Mic", 0x0 },
5526 { "Line", 0x2 },
5527 { "CD", 0x4 },
5528 { "Headphone", 0x6 },
5529 { "Mixer", 0x5 },
5530 },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005531 },
5532};
Michael Schwingencc959482009-02-22 18:58:45 +01005533
5534/* Maxdata Favorit 100XS */
5535static struct hda_input_mux alc260_favorit100_capture_sources[2] = {
5536 {
5537 .num_items = 2,
5538 .items = {
5539 { "Line/Mic", 0x0 },
5540 { "CD", 0x4 },
5541 },
5542 },
5543 {
5544 .num_items = 3,
5545 .items = {
5546 { "Line/Mic", 0x0 },
5547 { "CD", 0x4 },
5548 { "Mixer", 0x5 },
5549 },
5550 },
5551};
5552
Linus Torvalds1da177e2005-04-16 15:20:36 -07005553/*
5554 * This is just place-holder, so there's something for alc_build_pcms to look
5555 * at when it calculates the maximum number of channels. ALC260 has no mixer
5556 * element which allows changing the channel mode, so the verb list is
5557 * never used.
5558 */
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01005559static struct hda_channel_mode alc260_modes[1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560 { 2, NULL },
5561};
5562
Kailang Yangdf694da2005-12-05 19:42:22 +01005563
5564/* Mixer combinations
5565 *
5566 * basic: base_output + input + pc_beep + capture
5567 * HP: base_output + input + capture_alt
5568 * HP_3013: hp_3013 + input + capture
5569 * fujitsu: fujitsu + capture
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005570 * acer: acer + capture
Kailang Yangdf694da2005-12-05 19:42:22 +01005571 */
5572
5573static struct snd_kcontrol_new alc260_base_output_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02005574 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01005575 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01005576 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5577 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
5578 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
5579 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
5580 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005581};
Kailang Yangdf694da2005-12-05 19:42:22 +01005582
5583static struct snd_kcontrol_new alc260_input_mixer[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5585 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5586 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5587 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5588 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5589 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5590 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
5591 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592 { } /* end */
5593};
5594
Takashi Iwaibec15c32008-01-28 18:16:30 +01005595/* update HP, line and mono out pins according to the master switch */
5596static void alc260_hp_master_update(struct hda_codec *codec,
5597 hda_nid_t hp, hda_nid_t line,
5598 hda_nid_t mono)
5599{
5600 struct alc_spec *spec = codec->spec;
5601 unsigned int val = spec->master_sw ? PIN_HP : 0;
5602 /* change HP and line-out pins */
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005603 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005604 val);
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005605 snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005606 val);
5607 /* mono (speaker) depending on the HP jack sense */
5608 val = (val && !spec->jack_present) ? PIN_OUT : 0;
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005609 snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005610 val);
5611}
5612
5613static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
5614 struct snd_ctl_elem_value *ucontrol)
5615{
5616 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5617 struct alc_spec *spec = codec->spec;
5618 *ucontrol->value.integer.value = spec->master_sw;
5619 return 0;
5620}
5621
5622static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
5623 struct snd_ctl_elem_value *ucontrol)
5624{
5625 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5626 struct alc_spec *spec = codec->spec;
5627 int val = !!*ucontrol->value.integer.value;
5628 hda_nid_t hp, line, mono;
5629
5630 if (val == spec->master_sw)
5631 return 0;
5632 spec->master_sw = val;
5633 hp = (kcontrol->private_value >> 16) & 0xff;
5634 line = (kcontrol->private_value >> 8) & 0xff;
5635 mono = kcontrol->private_value & 0xff;
5636 alc260_hp_master_update(codec, hp, line, mono);
5637 return 1;
5638}
5639
5640static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
5641 {
5642 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5643 .name = "Master Playback Switch",
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01005644 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005645 .info = snd_ctl_boolean_mono_info,
5646 .get = alc260_hp_master_sw_get,
5647 .put = alc260_hp_master_sw_put,
5648 .private_value = (0x0f << 16) | (0x10 << 8) | 0x11
5649 },
5650 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5651 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
5652 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5653 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
5654 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
5655 HDA_OUTPUT),
5656 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
5657 { } /* end */
5658};
5659
5660static struct hda_verb alc260_hp_unsol_verbs[] = {
5661 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5662 {},
5663};
5664
5665static void alc260_hp_automute(struct hda_codec *codec)
5666{
5667 struct alc_spec *spec = codec->spec;
Takashi Iwaibec15c32008-01-28 18:16:30 +01005668
Wu Fengguang864f92b2009-11-18 12:38:02 +08005669 spec->jack_present = snd_hda_jack_detect(codec, 0x10);
Takashi Iwaibec15c32008-01-28 18:16:30 +01005670 alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
5671}
5672
5673static void alc260_hp_unsol_event(struct hda_codec *codec, unsigned int res)
5674{
5675 if ((res >> 26) == ALC880_HP_EVENT)
5676 alc260_hp_automute(codec);
5677}
5678
Kailang Yangdf694da2005-12-05 19:42:22 +01005679static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
Takashi Iwaibec15c32008-01-28 18:16:30 +01005680 {
5681 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5682 .name = "Master Playback Switch",
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +01005683 .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
Takashi Iwaibec15c32008-01-28 18:16:30 +01005684 .info = snd_ctl_boolean_mono_info,
5685 .get = alc260_hp_master_sw_get,
5686 .put = alc260_hp_master_sw_put,
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005687 .private_value = (0x15 << 16) | (0x10 << 8) | 0x11
Takashi Iwaibec15c32008-01-28 18:16:30 +01005688 },
Kailang Yangdf694da2005-12-05 19:42:22 +01005689 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5690 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
5691 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
5692 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
5693 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5694 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +01005695 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
5696 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
Takashi Iwai16ded522005-06-10 19:58:24 +02005697 { } /* end */
5698};
5699
Kailang Yang3f878302008-08-26 13:02:23 +02005700static struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
5701 .ops = &snd_hda_bind_vol,
5702 .values = {
5703 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
5704 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
5705 HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT),
5706 0
5707 },
5708};
5709
5710static struct hda_bind_ctls alc260_dc7600_bind_switch = {
5711 .ops = &snd_hda_bind_sw,
5712 .values = {
5713 HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
5714 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
5715 0
5716 },
5717};
5718
5719static struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
5720 HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
5721 HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
5722 HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
5723 HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
5724 { } /* end */
5725};
5726
Takashi Iwaibec15c32008-01-28 18:16:30 +01005727static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
5728 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
5729 {},
5730};
5731
5732static void alc260_hp_3013_automute(struct hda_codec *codec)
5733{
5734 struct alc_spec *spec = codec->spec;
Takashi Iwaibec15c32008-01-28 18:16:30 +01005735
Wu Fengguang864f92b2009-11-18 12:38:02 +08005736 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwai30cde0a2008-11-07 14:49:28 +01005737 alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
Takashi Iwaibec15c32008-01-28 18:16:30 +01005738}
5739
5740static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
5741 unsigned int res)
5742{
5743 if ((res >> 26) == ALC880_HP_EVENT)
5744 alc260_hp_3013_automute(codec);
5745}
5746
Kailang Yang3f878302008-08-26 13:02:23 +02005747static void alc260_hp_3012_automute(struct hda_codec *codec)
5748{
Wu Fengguang864f92b2009-11-18 12:38:02 +08005749 unsigned int bits = snd_hda_jack_detect(codec, 0x10) ? 0 : PIN_OUT;
Kailang Yang3f878302008-08-26 13:02:23 +02005750
Kailang Yang3f878302008-08-26 13:02:23 +02005751 snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5752 bits);
5753 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5754 bits);
5755 snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
5756 bits);
5757}
5758
5759static void alc260_hp_3012_unsol_event(struct hda_codec *codec,
5760 unsigned int res)
5761{
5762 if ((res >> 26) == ALC880_HP_EVENT)
5763 alc260_hp_3012_automute(codec);
5764}
5765
5766/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005767 * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
5768 */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01005769static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005770 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01005771 HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005772 ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
Jonathan Woithea9430dd2005-09-16 19:12:48 +02005773 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5774 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5775 HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
5776 HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01005777 ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005778 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
5779 HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +01005780 { } /* end */
5781};
5782
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005783/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
5784 * versions of the ALC260 don't act on requests to enable mic bias from NID
5785 * 0x0f (used to drive the headphone jack in these laptops). The ALC260
5786 * datasheet doesn't mention this restriction. At this stage it's not clear
5787 * whether this behaviour is intentional or is a hardware bug in chip
5788 * revisions available in early 2006. Therefore for now allow the
5789 * "Headphone Jack Mode" control to span all choices, but if it turns out
5790 * that the lack of mic bias for this NID is intentional we could change the
5791 * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
5792 *
5793 * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
5794 * don't appear to make the mic bias available from the "line" jack, even
5795 * though the NID used for this jack (0x14) can supply it. The theory is
5796 * that perhaps Acer have included blocking capacitors between the ALC260
5797 * and the output jack. If this turns out to be the case for all such
5798 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
5799 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
Jonathan Woithebd869482006-11-28 11:35:52 +01005800 *
5801 * The C20x Tablet series have a mono internal speaker which is controlled
5802 * via the chip's Mono sum widget and pin complex, so include the necessary
5803 * controls for such models. On models without a "mono speaker" the control
5804 * won't do anything.
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005805 */
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005806static struct snd_kcontrol_new alc260_acer_mixer[] = {
5807 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5808 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02005809 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005810 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
Jonathan Woithebd869482006-11-28 11:35:52 +01005811 HDA_OUTPUT),
Takashi Iwai31bffaa2008-02-27 16:10:44 +01005812 HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
Jonathan Woithebd869482006-11-28 11:35:52 +01005813 HDA_INPUT),
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005814 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5815 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
5816 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5817 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5818 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5819 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5820 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5821 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01005822 { } /* end */
5823};
5824
Michael Schwingencc959482009-02-22 18:58:45 +01005825/* Maxdata Favorit 100XS: one output and one input (0x12) jack
5826 */
5827static struct snd_kcontrol_new alc260_favorit100_mixer[] = {
5828 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5829 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
5830 ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
5831 HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5832 HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5833 ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5834 { } /* end */
5835};
5836
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005837/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
5838 * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
5839 */
5840static struct snd_kcontrol_new alc260_will_mixer[] = {
5841 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5842 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
5843 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5844 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5845 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5846 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5847 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5848 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
5849 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
5850 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005851 { } /* end */
5852};
5853
5854/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
5855 * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
5856 */
5857static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
5858 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
5859 HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
5860 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
5861 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
5862 ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
5863 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
5864 HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
5865 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
5866 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
5867 ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
5868 { } /* end */
5869};
5870
Kailang Yangdf694da2005-12-05 19:42:22 +01005871/*
5872 * initialization verbs
5873 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874static struct hda_verb alc260_init_verbs[] = {
5875 /* Line In pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02005876 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877 /* CD pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02005878 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879 /* Mic1 (rear panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02005880 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881 /* Mic2 (front panel) pin widget for input and vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02005882 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005883 /* LINE-2 is used for line-out in rear */
Takashi Iwai05acb862005-06-10 19:50:25 +02005884 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885 /* select line-out */
Jonathan Woithefd56f2d2006-01-24 10:35:46 +01005886 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005887 /* LINE-OUT pin */
Takashi Iwai05acb862005-06-10 19:50:25 +02005888 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005889 /* enable HP */
Takashi Iwai05acb862005-06-10 19:50:25 +02005890 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005891 /* enable Mono */
Takashi Iwai05acb862005-06-10 19:50:25 +02005892 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5893 /* mute capture amp left and right */
Takashi Iwai16ded522005-06-10 19:58:24 +02005894 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005895 /* set connection select to line in (default select for this ADC) */
5896 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai16ded522005-06-10 19:58:24 +02005897 /* mute capture amp left and right */
5898 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5899 /* set connection select to line in (default select for this ADC) */
5900 {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai05acb862005-06-10 19:50:25 +02005901 /* set vol=0 Line-Out mixer amp left and right */
5902 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5903 /* unmute pin widget amp left and right (no gain on this amp) */
5904 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5905 /* set vol=0 HP mixer amp left and right */
5906 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5907 /* unmute pin widget amp left and right (no gain on this amp) */
5908 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5909 /* set vol=0 Mono mixer amp left and right */
5910 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5911 /* unmute pin widget amp left and right (no gain on this amp) */
5912 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
5913 /* unmute LINE-2 out pin */
5914 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005915 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
5916 * Line In 2 = 0x03
5917 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02005918 /* mute analog inputs */
5919 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5920 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5921 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5922 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5923 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
Takashi Iwai05acb862005-06-10 19:50:25 +02005925 /* mute Front out path */
5926 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5927 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5928 /* mute Headphone out path */
5929 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5930 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5931 /* mute Mono out path */
5932 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5933 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934 { }
5935};
5936
Takashi Iwai474167d2006-05-17 17:17:43 +02005937#if 0 /* should be identical with alc260_init_verbs? */
Kailang Yangdf694da2005-12-05 19:42:22 +01005938static struct hda_verb alc260_hp_init_verbs[] = {
5939 /* Headphone and output */
5940 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
5941 /* mono output */
5942 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5943 /* Mic1 (rear panel) pin widget for input and vref at 80% */
5944 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5945 /* Mic2 (front panel) pin widget for input and vref at 80% */
5946 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5947 /* Line In pin widget for input */
5948 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5949 /* Line-2 pin widget for output */
5950 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5951 /* CD pin widget for input */
5952 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5953 /* unmute amp left and right */
5954 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
5955 /* set connection select to line in (default select for this ADC) */
5956 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
5957 /* unmute Line-Out mixer amp left and right (volume = 0) */
5958 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5959 /* mute pin widget amp left and right (no gain on this amp) */
5960 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
5961 /* unmute HP mixer amp left and right (volume = 0) */
5962 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
5963 /* mute pin widget amp left and right (no gain on this amp) */
5964 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02005965 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
5966 * Line In 2 = 0x03
5967 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02005968 /* mute analog inputs */
5969 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5970 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5971 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5972 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5973 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01005974 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
5975 /* Unmute Front out path */
5976 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5977 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5978 /* Unmute Headphone out path */
5979 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5980 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5981 /* Unmute Mono out path */
5982 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
5983 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
5984 { }
5985};
Takashi Iwai474167d2006-05-17 17:17:43 +02005986#endif
Kailang Yangdf694da2005-12-05 19:42:22 +01005987
5988static struct hda_verb alc260_hp_3013_init_verbs[] = {
5989 /* Line out and output */
5990 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5991 /* mono output */
5992 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
5993 /* Mic1 (rear panel) pin widget for input and vref at 80% */
5994 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5995 /* Mic2 (front panel) pin widget for input and vref at 80% */
5996 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5997 /* Line In pin widget for input */
5998 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
5999 /* Headphone pin widget for output */
6000 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6001 /* CD pin widget for input */
6002 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
6003 /* unmute amp left and right */
6004 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
6005 /* set connection select to line in (default select for this ADC) */
6006 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
6007 /* unmute Line-Out mixer amp left and right (volume = 0) */
6008 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6009 /* mute pin widget amp left and right (no gain on this amp) */
6010 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6011 /* unmute HP mixer amp left and right (volume = 0) */
6012 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
6013 /* mute pin widget amp left and right (no gain on this amp) */
6014 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006015 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
6016 * Line In 2 = 0x03
6017 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02006018 /* mute analog inputs */
6019 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6020 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6021 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6022 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6023 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01006024 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
6025 /* Unmute Front out path */
6026 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6027 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6028 /* Unmute Headphone out path */
6029 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6030 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6031 /* Unmute Mono out path */
6032 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6033 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6034 { }
6035};
6036
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006037/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006038 * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
6039 * audio = 0x16, internal speaker = 0x10.
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006040 */
6041static struct hda_verb alc260_fujitsu_init_verbs[] = {
6042 /* Disable all GPIOs */
6043 {0x01, AC_VERB_SET_GPIO_MASK, 0},
6044 /* Internal speaker is connected to headphone pin */
6045 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6046 /* Headphone/Line-out jack connects to Line1 pin; make it an output */
6047 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Jonathan Woithef7ace402006-02-28 11:46:14 +01006048 /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
6049 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
6050 /* Ensure all other unused pins are disabled and muted. */
6051 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6052 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006053 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
Jonathan Woithef7ace402006-02-28 11:46:14 +01006054 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006055 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
Jonathan Woithef7ace402006-02-28 11:46:14 +01006056 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6057 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6058 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006059
Jonathan Woithef7ace402006-02-28 11:46:14 +01006060 /* Disable digital (SPDIF) pins */
6061 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6062 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01006063
Kailang Yangea1fb292008-08-26 12:58:38 +02006064 /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
Jonathan Woithef7ace402006-02-28 11:46:14 +01006065 * when acting as an output.
6066 */
6067 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6068
6069 /* Start with output sum widgets muted and their output gains at min */
Takashi Iwai8b33a5a2006-02-09 11:57:01 +01006070 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6071 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6072 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6073 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6074 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6075 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6076 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6077 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6078 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006079
Jonathan Woithef7ace402006-02-28 11:46:14 +01006080 /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
6081 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6082 /* Unmute Line1 pin widget output buffer since it starts as an output.
6083 * If the pin mode is changed by the user the pin mode control will
6084 * take care of enabling the pin's input/output buffers as needed.
6085 * Therefore there's no need to enable the input buffer at this
6086 * stage.
Jonathan Woithecdcd9262006-02-28 11:36:42 +01006087 */
Jonathan Woithef7ace402006-02-28 11:46:14 +01006088 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +02006089 /* Unmute input buffer of pin widget used for Line-in (no equiv
Jonathan Woithecdcd9262006-02-28 11:36:42 +01006090 * mixer ctrl)
6091 */
Jonathan Woithef7ace402006-02-28 11:46:14 +01006092 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006093
Jonathan Woithef7ace402006-02-28 11:46:14 +01006094 /* Mute capture amp left and right */
6095 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +02006096 /* Set ADC connection select to match default mixer setting - line
Jonathan Woithef7ace402006-02-28 11:46:14 +01006097 * in (on mic1 pin)
6098 */
6099 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006100
Jonathan Woithef7ace402006-02-28 11:46:14 +01006101 /* Do the same for the second ADC: mute capture input amp and
6102 * set ADC connection to line in (on mic1 pin)
6103 */
6104 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6105 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithe4c5186e2006-02-09 11:53:48 +01006106
Jonathan Woithef7ace402006-02-28 11:46:14 +01006107 /* Mute all inputs to mixer widget (even unconnected ones) */
6108 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6109 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6110 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6111 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6112 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6113 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6114 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6115 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
Takashi Iwai4a471b72005-12-07 13:56:29 +01006116
6117 { }
Jonathan Woithea9430dd2005-09-16 19:12:48 +02006118};
6119
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006120/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
6121 * similar laptops (adapted from Fujitsu init verbs).
6122 */
6123static struct hda_verb alc260_acer_init_verbs[] = {
6124 /* On TravelMate laptops, GPIO 0 enables the internal speaker and
6125 * the headphone jack. Turn this on and rely on the standard mute
6126 * methods whenever the user wants to turn these outputs off.
6127 */
6128 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6129 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6130 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
6131 /* Internal speaker/Headphone jack is connected to Line-out pin */
6132 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6133 /* Internal microphone/Mic jack is connected to Mic1 pin */
6134 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
6135 /* Line In jack is connected to Line1 pin */
6136 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Jonathan Woithebd869482006-11-28 11:35:52 +01006137 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
6138 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006139 /* Ensure all other unused pins are disabled and muted. */
6140 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6141 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006142 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6143 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6144 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6145 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6146 /* Disable digital (SPDIF) pins */
6147 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6148 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6149
Kailang Yangea1fb292008-08-26 12:58:38 +02006150 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006151 * bus when acting as outputs.
6152 */
6153 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6154 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6155
6156 /* Start with output sum widgets muted and their output gains at min */
6157 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6158 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6159 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6160 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6161 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6162 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6163 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6164 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6165 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6166
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006167 /* Unmute Line-out pin widget amp left and right
6168 * (no equiv mixer ctrl)
6169 */
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006170 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Jonathan Woithebd869482006-11-28 11:35:52 +01006171 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
6172 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006173 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
6174 * inputs. If the pin mode is changed by the user the pin mode control
6175 * will take care of enabling the pin's input/output buffers as needed.
6176 * Therefore there's no need to enable the input buffer at this
6177 * stage.
6178 */
6179 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6180 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6181
6182 /* Mute capture amp left and right */
6183 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6184 /* Set ADC connection select to match default mixer setting - mic
6185 * (on mic1 pin)
6186 */
6187 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6188
6189 /* Do similar with the second ADC: mute capture input amp and
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006190 * set ADC connection to mic to match ALSA's default state.
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006191 */
6192 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006193 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006194
6195 /* Mute all inputs to mixer widget (even unconnected ones) */
6196 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6197 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6198 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6199 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6200 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6201 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6202 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6203 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6204
6205 { }
6206};
6207
Michael Schwingencc959482009-02-22 18:58:45 +01006208/* Initialisation sequence for Maxdata Favorit 100XS
6209 * (adapted from Acer init verbs).
6210 */
6211static struct hda_verb alc260_favorit100_init_verbs[] = {
6212 /* GPIO 0 enables the output jack.
6213 * Turn this on and rely on the standard mute
6214 * methods whenever the user wants to turn these outputs off.
6215 */
6216 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6217 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6218 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
6219 /* Line/Mic input jack is connected to Mic1 pin */
6220 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
6221 /* Ensure all other unused pins are disabled and muted. */
6222 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6223 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6224 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6225 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6226 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6227 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6228 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6229 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6230 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
6231 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6232 /* Disable digital (SPDIF) pins */
6233 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6234 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6235
6236 /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
6237 * bus when acting as outputs.
6238 */
6239 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6240 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6241
6242 /* Start with output sum widgets muted and their output gains at min */
6243 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6244 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6245 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6246 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6247 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6248 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6249 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6250 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6251 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6252
6253 /* Unmute Line-out pin widget amp left and right
6254 * (no equiv mixer ctrl)
6255 */
6256 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6257 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
6258 * inputs. If the pin mode is changed by the user the pin mode control
6259 * will take care of enabling the pin's input/output buffers as needed.
6260 * Therefore there's no need to enable the input buffer at this
6261 * stage.
6262 */
6263 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6264
6265 /* Mute capture amp left and right */
6266 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6267 /* Set ADC connection select to match default mixer setting - mic
6268 * (on mic1 pin)
6269 */
6270 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6271
6272 /* Do similar with the second ADC: mute capture input amp and
6273 * set ADC connection to mic to match ALSA's default state.
6274 */
6275 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6276 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6277
6278 /* Mute all inputs to mixer widget (even unconnected ones) */
6279 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6280 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6281 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6282 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6283 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6284 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6285 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6286 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6287
6288 { }
6289};
6290
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006291static struct hda_verb alc260_will_verbs[] = {
6292 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6293 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
6294 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
6295 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
6296 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
6297 {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
6298 {}
6299};
6300
6301static struct hda_verb alc260_replacer_672v_verbs[] = {
6302 {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
6303 {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
6304 {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
6305
6306 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
6307 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6308 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
6309
6310 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6311 {}
6312};
6313
6314/* toggle speaker-output according to the hp-jack state */
6315static void alc260_replacer_672v_automute(struct hda_codec *codec)
6316{
6317 unsigned int present;
6318
6319 /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
Wu Fengguang864f92b2009-11-18 12:38:02 +08006320 present = snd_hda_jack_detect(codec, 0x0f);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006321 if (present) {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02006322 snd_hda_codec_write_cache(codec, 0x01, 0,
6323 AC_VERB_SET_GPIO_DATA, 1);
6324 snd_hda_codec_write_cache(codec, 0x0f, 0,
6325 AC_VERB_SET_PIN_WIDGET_CONTROL,
6326 PIN_HP);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006327 } else {
Takashi Iwai82beb8f2007-08-10 17:09:26 +02006328 snd_hda_codec_write_cache(codec, 0x01, 0,
6329 AC_VERB_SET_GPIO_DATA, 0);
6330 snd_hda_codec_write_cache(codec, 0x0f, 0,
6331 AC_VERB_SET_PIN_WIDGET_CONTROL,
6332 PIN_OUT);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006333 }
6334}
6335
6336static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
6337 unsigned int res)
6338{
6339 if ((res >> 26) == ALC880_HP_EVENT)
6340 alc260_replacer_672v_automute(codec);
6341}
6342
Kailang Yang3f878302008-08-26 13:02:23 +02006343static struct hda_verb alc260_hp_dc7600_verbs[] = {
6344 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
6345 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
6346 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6347 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6348 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6349 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6350 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
6351 {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6352 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6353 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6354 {}
6355};
6356
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006357/* Test configuration for debugging, modelled after the ALC880 test
6358 * configuration.
6359 */
6360#ifdef CONFIG_SND_DEBUG
6361static hda_nid_t alc260_test_dac_nids[1] = {
6362 0x02,
6363};
6364static hda_nid_t alc260_test_adc_nids[2] = {
6365 0x04, 0x05,
6366};
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006367/* For testing the ALC260, each input MUX needs its own definition since
Kailang Yangea1fb292008-08-26 12:58:38 +02006368 * the signal assignments are different. This assumes that the first ADC
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006369 * is NID 0x04.
Jonathan Woithe17e7aec2006-02-28 11:35:18 +01006370 */
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006371static struct hda_input_mux alc260_test_capture_sources[2] = {
6372 {
6373 .num_items = 7,
6374 .items = {
6375 { "MIC1 pin", 0x0 },
6376 { "MIC2 pin", 0x1 },
6377 { "LINE1 pin", 0x2 },
6378 { "LINE2 pin", 0x3 },
6379 { "CD pin", 0x4 },
6380 { "LINE-OUT pin", 0x5 },
6381 { "HP-OUT pin", 0x6 },
6382 },
6383 },
6384 {
6385 .num_items = 8,
6386 .items = {
6387 { "MIC1 pin", 0x0 },
6388 { "MIC2 pin", 0x1 },
6389 { "LINE1 pin", 0x2 },
6390 { "LINE2 pin", 0x3 },
6391 { "CD pin", 0x4 },
6392 { "Mixer", 0x5 },
6393 { "LINE-OUT pin", 0x6 },
6394 { "HP-OUT pin", 0x7 },
6395 },
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006396 },
6397};
6398static struct snd_kcontrol_new alc260_test_mixer[] = {
6399 /* Output driver widgets */
6400 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
6401 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
6402 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
6403 HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
6404 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
6405 HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
6406
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006407 /* Modes for retasking pin widgets
6408 * Note: the ALC260 doesn't seem to act on requests to enable mic
6409 * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
6410 * mention this restriction. At this stage it's not clear whether
6411 * this behaviour is intentional or is a hardware bug in chip
6412 * revisions available at least up until early 2006. Therefore for
6413 * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
6414 * choices, but if it turns out that the lack of mic bias for these
6415 * NIDs is intentional we could change their modes from
6416 * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
6417 */
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006418 ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
6419 ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
6420 ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
6421 ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
6422 ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
6423 ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
6424
6425 /* Loopback mixer controls */
6426 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
6427 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
6428 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
6429 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
6430 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
6431 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
6432 HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
6433 HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
6434 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
6435 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006436 HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
6437 HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
6438 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
6439 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
Jonathan Woithe5c8f8582006-02-28 11:43:27 +01006440
6441 /* Controls for GPIO pins, assuming they are configured as outputs */
6442 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
6443 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
6444 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
6445 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
6446
Jonathan Woithe92621f12006-02-28 11:47:47 +01006447 /* Switches to allow the digital IO pins to be enabled. The datasheet
6448 * is ambigious as to which NID is which; testing on laptops which
Kailang Yangea1fb292008-08-26 12:58:38 +02006449 * make this output available should provide clarification.
Jonathan Woithe92621f12006-02-28 11:47:47 +01006450 */
6451 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
6452 ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
6453
Jonathan Woithef8225f62008-01-08 12:16:54 +01006454 /* A switch allowing EAPD to be enabled. Some laptops seem to use
6455 * this output to turn on an external amplifier.
6456 */
6457 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
6458 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
6459
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006460 { } /* end */
6461};
6462static struct hda_verb alc260_test_init_verbs[] = {
Jonathan Woithe5c8f8582006-02-28 11:43:27 +01006463 /* Enable all GPIOs as outputs with an initial value of 0 */
6464 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
6465 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
6466 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
6467
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006468 /* Enable retasking pins as output, initially without power amp */
6469 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6470 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6471 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6472 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6473 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6474 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
6475
Jonathan Woithe92621f12006-02-28 11:47:47 +01006476 /* Disable digital (SPDIF) pins initially, but users can enable
6477 * them via a mixer switch. In the case of SPDIF-out, this initverb
6478 * payload also sets the generation to 0, output to be in "consumer"
6479 * PCM format, copyright asserted, no pre-emphasis and no validity
6480 * control.
6481 */
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006482 {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
6483 {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
6484
Kailang Yangea1fb292008-08-26 12:58:38 +02006485 /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006486 * OUT1 sum bus when acting as an output.
6487 */
6488 {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
6489 {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
6490 {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
6491 {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
6492
6493 /* Start with output sum widgets muted and their output gains at min */
6494 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6495 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6496 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6497 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6498 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6499 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6500 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6501 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6502 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6503
Jonathan Woithecdcd9262006-02-28 11:36:42 +01006504 /* Unmute retasking pin widget output buffers since the default
6505 * state appears to be output. As the pin mode is changed by the
6506 * user the pin mode control will take care of enabling the pin's
6507 * input/output buffers as needed.
6508 */
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006509 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6510 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6511 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6512 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6513 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6514 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6515 /* Also unmute the mono-out pin widget */
6516 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
6517
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006518 /* Mute capture amp left and right */
6519 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Jonathan Woithef7ace402006-02-28 11:46:14 +01006520 /* Set ADC connection select to match default mixer setting (mic1
6521 * pin)
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006522 */
6523 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6524
6525 /* Do the same for the second ADC: mute capture input amp and
Jonathan Woithef7ace402006-02-28 11:46:14 +01006526 * set ADC connection to mic1 pin
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006527 */
6528 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6529 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6530
6531 /* Mute all inputs to mixer widget (even unconnected ones) */
6532 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
6533 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
6534 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
6535 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
6536 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
6537 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
6538 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
6539 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
6540
6541 { }
6542};
6543#endif
6544
Takashi Iwai63300792008-01-24 15:31:36 +01006545#define alc260_pcm_analog_playback alc880_pcm_analog_alt_playback
6546#define alc260_pcm_analog_capture alc880_pcm_analog_capture
Linus Torvalds1da177e2005-04-16 15:20:36 -07006547
Takashi Iwaia3bcba32005-12-06 19:05:29 +01006548#define alc260_pcm_digital_playback alc880_pcm_digital_playback
6549#define alc260_pcm_digital_capture alc880_pcm_digital_capture
6550
Kailang Yangdf694da2005-12-05 19:42:22 +01006551/*
6552 * for BIOS auto-configuration
6553 */
6554
6555static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
Takashi Iwai863b4512008-10-21 17:01:47 +02006556 const char *pfx, int *vol_bits)
Kailang Yangdf694da2005-12-05 19:42:22 +01006557{
6558 hda_nid_t nid_vol;
6559 unsigned long vol_val, sw_val;
Kailang Yangdf694da2005-12-05 19:42:22 +01006560 int err;
6561
6562 if (nid >= 0x0f && nid < 0x11) {
6563 nid_vol = nid - 0x7;
6564 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
6565 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
6566 } else if (nid == 0x11) {
6567 nid_vol = nid - 0x7;
6568 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
6569 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
6570 } else if (nid >= 0x12 && nid <= 0x15) {
6571 nid_vol = 0x08;
6572 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
6573 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
6574 } else
6575 return 0; /* N/A */
Kailang Yangea1fb292008-08-26 12:58:38 +02006576
Takashi Iwai863b4512008-10-21 17:01:47 +02006577 if (!(*vol_bits & (1 << nid_vol))) {
6578 /* first control for the volume widget */
Takashi Iwai0afe5f82009-10-02 09:20:00 +02006579 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
Takashi Iwai863b4512008-10-21 17:01:47 +02006580 if (err < 0)
6581 return err;
6582 *vol_bits |= (1 << nid_vol);
6583 }
Takashi Iwai0afe5f82009-10-02 09:20:00 +02006584 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006585 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006586 return err;
6587 return 1;
6588}
6589
6590/* add playback controls from the parsed DAC table */
6591static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
6592 const struct auto_pin_cfg *cfg)
6593{
6594 hda_nid_t nid;
6595 int err;
Takashi Iwai863b4512008-10-21 17:01:47 +02006596 int vols = 0;
Kailang Yangdf694da2005-12-05 19:42:22 +01006597
6598 spec->multiout.num_dacs = 1;
6599 spec->multiout.dac_nids = spec->private_dac_nids;
6600 spec->multiout.dac_nids[0] = 0x02;
6601
6602 nid = cfg->line_out_pins[0];
6603 if (nid) {
Takashi Iwai23112d62009-08-25 16:07:08 +02006604 const char *pfx;
6605 if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
6606 pfx = "Master";
6607 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
6608 pfx = "Speaker";
6609 else
6610 pfx = "Front";
6611 err = alc260_add_playback_controls(spec, nid, pfx, &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006612 if (err < 0)
6613 return err;
6614 }
6615
Takashi Iwai82bc9552006-03-21 11:24:42 +01006616 nid = cfg->speaker_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006617 if (nid) {
Takashi Iwai863b4512008-10-21 17:01:47 +02006618 err = alc260_add_playback_controls(spec, nid, "Speaker", &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006619 if (err < 0)
6620 return err;
6621 }
6622
Takashi Iwaieb06ed82006-09-20 17:10:27 +02006623 nid = cfg->hp_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006624 if (nid) {
Takashi Iwai863b4512008-10-21 17:01:47 +02006625 err = alc260_add_playback_controls(spec, nid, "Headphone",
6626 &vols);
Kailang Yangdf694da2005-12-05 19:42:22 +01006627 if (err < 0)
6628 return err;
6629 }
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006630 return 0;
Kailang Yangdf694da2005-12-05 19:42:22 +01006631}
6632
6633/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +02006634static int alc260_auto_create_input_ctls(struct hda_codec *codec,
Kailang Yangdf694da2005-12-05 19:42:22 +01006635 const struct auto_pin_cfg *cfg)
6636{
Takashi Iwai05f5f472009-08-25 13:10:18 +02006637 return alc_auto_create_input_ctls(codec, cfg, 0x07, 0x04, 0x05);
Kailang Yangdf694da2005-12-05 19:42:22 +01006638}
6639
6640static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
6641 hda_nid_t nid, int pin_type,
6642 int sel_idx)
6643{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006644 alc_set_pin_output(codec, nid, pin_type);
Kailang Yangdf694da2005-12-05 19:42:22 +01006645 /* need the manual connection? */
6646 if (nid >= 0x12) {
6647 int idx = nid - 0x12;
6648 snd_hda_codec_write(codec, idx + 0x0b, 0,
6649 AC_VERB_SET_CONNECT_SEL, sel_idx);
Kailang Yangdf694da2005-12-05 19:42:22 +01006650 }
6651}
6652
6653static void alc260_auto_init_multi_out(struct hda_codec *codec)
6654{
6655 struct alc_spec *spec = codec->spec;
6656 hda_nid_t nid;
6657
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006658 nid = spec->autocfg.line_out_pins[0];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02006659 if (nid) {
6660 int pin_type = get_pin_type(spec->autocfg.line_out_type);
6661 alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
6662 }
Kailang Yangea1fb292008-08-26 12:58:38 +02006663
Takashi Iwai82bc9552006-03-21 11:24:42 +01006664 nid = spec->autocfg.speaker_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006665 if (nid)
6666 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
6667
Takashi Iwaieb06ed82006-09-20 17:10:27 +02006668 nid = spec->autocfg.hp_pins[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006669 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +02006670 alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006671}
Kailang Yangdf694da2005-12-05 19:42:22 +01006672
6673#define ALC260_PIN_CD_NID 0x16
6674static void alc260_auto_init_analog_input(struct hda_codec *codec)
6675{
6676 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +02006677 struct auto_pin_cfg *cfg = &spec->autocfg;
Kailang Yangdf694da2005-12-05 19:42:22 +01006678 int i;
6679
Takashi Iwai66ceeb62010-08-30 13:05:52 +02006680 for (i = 0; i < cfg->num_inputs; i++) {
6681 hda_nid_t nid = cfg->inputs[i].pin;
Kailang Yangdf694da2005-12-05 19:42:22 +01006682 if (nid >= 0x12) {
Takashi Iwai23f0c042009-02-26 13:03:58 +01006683 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +01006684 if (nid != ALC260_PIN_CD_NID &&
6685 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006686 snd_hda_codec_write(codec, nid, 0,
6687 AC_VERB_SET_AMP_GAIN_MUTE,
Kailang Yangdf694da2005-12-05 19:42:22 +01006688 AMP_OUT_MUTE);
6689 }
6690 }
6691}
6692
Takashi Iwai7f311a42010-04-09 17:32:23 +02006693#define alc260_auto_init_input_src alc880_auto_init_input_src
6694
Kailang Yangdf694da2005-12-05 19:42:22 +01006695/*
6696 * generic initialization of ADC, input mixers and output mixers
6697 */
6698static struct hda_verb alc260_volume_init_verbs[] = {
6699 /*
6700 * Unmute ADC0-1 and set the default input to mic-in
6701 */
6702 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
6703 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6704 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
6705 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +02006706
Kailang Yangdf694da2005-12-05 19:42:22 +01006707 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6708 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006709 * Note: PASD motherboards uses the Line In 2 as the input for
6710 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +01006711 */
6712 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +02006713 /* mute analog inputs */
6714 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
6715 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
6716 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
6717 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
6718 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +01006719
6720 /*
6721 * Set up output mixers (0x08 - 0x0a)
6722 */
6723 /* set vol=0 to output mixers */
6724 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6725 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6726 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6727 /* set up input amps for analog loopback */
6728 /* Amp Indices: DAC = 0, mixer = 1 */
6729 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6730 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6731 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6732 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6733 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6734 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +02006735
Kailang Yangdf694da2005-12-05 19:42:22 +01006736 { }
6737};
6738
6739static int alc260_parse_auto_config(struct hda_codec *codec)
6740{
6741 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01006742 int err;
6743 static hda_nid_t alc260_ignore[] = { 0x17, 0 };
6744
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006745 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
6746 alc260_ignore);
6747 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006748 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006749 err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
6750 if (err < 0)
Takashi Iwai4a471b72005-12-07 13:56:29 +01006751 return err;
Takashi Iwai603c4012008-07-30 15:01:44 +02006752 if (!spec->kctls.list)
Kailang Yangdf694da2005-12-05 19:42:22 +01006753 return 0; /* can't find valid BIOS pin config */
Takashi Iwai05f5f472009-08-25 13:10:18 +02006754 err = alc260_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02006755 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +01006756 return err;
6757
6758 spec->multiout.max_channels = 2;
6759
Takashi Iwai0852d7a2009-02-11 11:35:15 +01006760 if (spec->autocfg.dig_outs)
Kailang Yangdf694da2005-12-05 19:42:22 +01006761 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
Takashi Iwai603c4012008-07-30 15:01:44 +02006762 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +01006763 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +01006764
Takashi Iwaid88897e2008-10-31 15:01:37 +01006765 add_verb(spec, alc260_volume_init_verbs);
Kailang Yangdf694da2005-12-05 19:42:22 +01006766
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006767 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -02006768 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +01006769
Kailang Yang6227cdc2010-02-25 08:36:52 +01006770 alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +02006771
Kailang Yangdf694da2005-12-05 19:42:22 +01006772 return 1;
6773}
6774
Takashi Iwaiae6b8132006-03-03 16:47:17 +01006775/* additional initialization for auto-configuration model */
6776static void alc260_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +01006777{
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006778 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01006779 alc260_auto_init_multi_out(codec);
6780 alc260_auto_init_analog_input(codec);
Takashi Iwai7f311a42010-04-09 17:32:23 +02006781 alc260_auto_init_input_src(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +02006782 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +01006783 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +02006784 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +01006785}
6786
Takashi Iwaicb53c622007-08-10 17:21:45 +02006787#ifdef CONFIG_SND_HDA_POWER_SAVE
6788static struct hda_amp_list alc260_loopbacks[] = {
6789 { 0x07, HDA_INPUT, 0 },
6790 { 0x07, HDA_INPUT, 1 },
6791 { 0x07, HDA_INPUT, 2 },
6792 { 0x07, HDA_INPUT, 3 },
6793 { 0x07, HDA_INPUT, 4 },
6794 { } /* end */
6795};
6796#endif
6797
Kailang Yangdf694da2005-12-05 19:42:22 +01006798/*
Takashi Iwaifc091762010-08-04 23:53:36 +02006799 * Pin config fixes
6800 */
6801enum {
6802 PINFIX_HP_DC5750,
6803};
6804
Takashi Iwaifc091762010-08-04 23:53:36 +02006805static const struct alc_fixup alc260_fixups[] = {
6806 [PINFIX_HP_DC5750] = {
Takashi Iwai73413b12010-08-30 09:39:57 +02006807 .pins = (const struct alc_pincfg[]) {
6808 { 0x11, 0x90130110 }, /* speaker */
6809 { }
6810 }
Takashi Iwaifc091762010-08-04 23:53:36 +02006811 },
6812};
6813
6814static struct snd_pci_quirk alc260_fixup_tbl[] = {
6815 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
6816 {}
6817};
6818
6819/*
Kailang Yangdf694da2005-12-05 19:42:22 +01006820 * ALC260 configurations
6821 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006822static const char *alc260_models[ALC260_MODEL_LAST] = {
6823 [ALC260_BASIC] = "basic",
6824 [ALC260_HP] = "hp",
6825 [ALC260_HP_3013] = "hp-3013",
Takashi Iwai2922c9a2008-08-27 18:12:42 +02006826 [ALC260_HP_DC7600] = "hp-dc7600",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006827 [ALC260_FUJITSU_S702X] = "fujitsu",
6828 [ALC260_ACER] = "acer",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006829 [ALC260_WILL] = "will",
6830 [ALC260_REPLACER_672V] = "replacer",
Michael Schwingencc959482009-02-22 18:58:45 +01006831 [ALC260_FAVORIT100] = "favorit100",
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006832#ifdef CONFIG_SND_DEBUG
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006833 [ALC260_TEST] = "test",
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006834#endif
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006835 [ALC260_AUTO] = "auto",
6836};
6837
6838static struct snd_pci_quirk alc260_cfg_tbl[] = {
Jonathan Woithebd869482006-11-28 11:35:52 +01006839 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
Daniel T Chen950200e2009-12-13 14:11:02 -05006840 SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006841 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
Michael Schwingencc959482009-02-22 18:58:45 +01006842 SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
Takashi Iwai9720b712007-03-13 21:46:23 +01006843 SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
Takashi Iwai4ac55982009-11-10 16:08:45 +01006844 SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006845 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
Jaroslav Kysela34ec8a02008-07-10 14:49:19 +02006846 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
Kailang Yang3f878302008-08-26 13:02:23 +02006847 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01006848 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
6849 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
6850 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
6851 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
6852 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
6853 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
6854 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
6855 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
6856 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006857 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01006858 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
Takashi Iwai16ded522005-06-10 19:58:24 +02006859 {}
6860};
6861
Kailang Yangdf694da2005-12-05 19:42:22 +01006862static struct alc_config_preset alc260_presets[] = {
6863 [ALC260_BASIC] = {
6864 .mixers = { alc260_base_output_mixer,
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01006865 alc260_input_mixer },
Kailang Yangdf694da2005-12-05 19:42:22 +01006866 .init_verbs = { alc260_init_verbs },
6867 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6868 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006869 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
Takashi Iwai9c4cc0b2010-03-15 09:07:52 +01006870 .adc_nids = alc260_dual_adc_nids,
Kailang Yangdf694da2005-12-05 19:42:22 +01006871 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6872 .channel_mode = alc260_modes,
6873 .input_mux = &alc260_capture_source,
6874 },
6875 [ALC260_HP] = {
Takashi Iwaibec15c32008-01-28 18:16:30 +01006876 .mixers = { alc260_hp_output_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006877 alc260_input_mixer },
Takashi Iwaibec15c32008-01-28 18:16:30 +01006878 .init_verbs = { alc260_init_verbs,
6879 alc260_hp_unsol_verbs },
Kailang Yangdf694da2005-12-05 19:42:22 +01006880 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6881 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006882 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6883 .adc_nids = alc260_adc_nids_alt,
Kailang Yangdf694da2005-12-05 19:42:22 +01006884 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6885 .channel_mode = alc260_modes,
6886 .input_mux = &alc260_capture_source,
Takashi Iwaibec15c32008-01-28 18:16:30 +01006887 .unsol_event = alc260_hp_unsol_event,
6888 .init_hook = alc260_hp_automute,
Kailang Yangdf694da2005-12-05 19:42:22 +01006889 },
Kailang Yang3f878302008-08-26 13:02:23 +02006890 [ALC260_HP_DC7600] = {
6891 .mixers = { alc260_hp_dc7600_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006892 alc260_input_mixer },
Kailang Yang3f878302008-08-26 13:02:23 +02006893 .init_verbs = { alc260_init_verbs,
6894 alc260_hp_dc7600_verbs },
6895 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6896 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006897 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6898 .adc_nids = alc260_adc_nids_alt,
Kailang Yang3f878302008-08-26 13:02:23 +02006899 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6900 .channel_mode = alc260_modes,
6901 .input_mux = &alc260_capture_source,
6902 .unsol_event = alc260_hp_3012_unsol_event,
6903 .init_hook = alc260_hp_3012_automute,
6904 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006905 [ALC260_HP_3013] = {
6906 .mixers = { alc260_hp_3013_mixer,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006907 alc260_input_mixer },
Takashi Iwaibec15c32008-01-28 18:16:30 +01006908 .init_verbs = { alc260_hp_3013_init_verbs,
6909 alc260_hp_3013_unsol_verbs },
Kailang Yangdf694da2005-12-05 19:42:22 +01006910 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6911 .dac_nids = alc260_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006912 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
6913 .adc_nids = alc260_adc_nids_alt,
Kailang Yangdf694da2005-12-05 19:42:22 +01006914 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6915 .channel_mode = alc260_modes,
6916 .input_mux = &alc260_capture_source,
Takashi Iwaibec15c32008-01-28 18:16:30 +01006917 .unsol_event = alc260_hp_3013_unsol_event,
6918 .init_hook = alc260_hp_3013_automute,
Kailang Yangdf694da2005-12-05 19:42:22 +01006919 },
6920 [ALC260_FUJITSU_S702X] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006921 .mixers = { alc260_fujitsu_mixer },
Kailang Yangdf694da2005-12-05 19:42:22 +01006922 .init_verbs = { alc260_fujitsu_init_verbs },
6923 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6924 .dac_nids = alc260_dac_nids,
Jonathan Woithed57fdac2006-02-28 11:38:35 +01006925 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6926 .adc_nids = alc260_dual_adc_nids,
Kailang Yangdf694da2005-12-05 19:42:22 +01006927 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6928 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006929 .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
6930 .input_mux = alc260_fujitsu_capture_sources,
Kailang Yangdf694da2005-12-05 19:42:22 +01006931 },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006932 [ALC260_ACER] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006933 .mixers = { alc260_acer_mixer },
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006934 .init_verbs = { alc260_acer_init_verbs },
6935 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6936 .dac_nids = alc260_dac_nids,
6937 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6938 .adc_nids = alc260_dual_adc_nids,
6939 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6940 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006941 .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
6942 .input_mux = alc260_acer_capture_sources,
Jonathan Woithe0bfc90e2006-02-28 11:45:11 +01006943 },
Michael Schwingencc959482009-02-22 18:58:45 +01006944 [ALC260_FAVORIT100] = {
6945 .mixers = { alc260_favorit100_mixer },
6946 .init_verbs = { alc260_favorit100_init_verbs },
6947 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6948 .dac_nids = alc260_dac_nids,
6949 .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
6950 .adc_nids = alc260_dual_adc_nids,
6951 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6952 .channel_mode = alc260_modes,
6953 .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
6954 .input_mux = alc260_favorit100_capture_sources,
6955 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006956 [ALC260_WILL] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006957 .mixers = { alc260_will_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006958 .init_verbs = { alc260_init_verbs, alc260_will_verbs },
6959 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6960 .dac_nids = alc260_dac_nids,
6961 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
6962 .adc_nids = alc260_adc_nids,
6963 .dig_out_nid = ALC260_DIGOUT_NID,
6964 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6965 .channel_mode = alc260_modes,
6966 .input_mux = &alc260_capture_source,
6967 },
6968 [ALC260_REPLACER_672V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006969 .mixers = { alc260_replacer_672v_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006970 .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
6971 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
6972 .dac_nids = alc260_dac_nids,
6973 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
6974 .adc_nids = alc260_adc_nids,
6975 .dig_out_nid = ALC260_DIGOUT_NID,
6976 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6977 .channel_mode = alc260_modes,
6978 .input_mux = &alc260_capture_source,
6979 .unsol_event = alc260_replacer_672v_unsol_event,
6980 .init_hook = alc260_replacer_672v_automute,
6981 },
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006982#ifdef CONFIG_SND_DEBUG
6983 [ALC260_TEST] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +01006984 .mixers = { alc260_test_mixer },
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006985 .init_verbs = { alc260_test_init_verbs },
6986 .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
6987 .dac_nids = alc260_test_dac_nids,
6988 .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
6989 .adc_nids = alc260_test_adc_nids,
6990 .num_channel_mode = ARRAY_SIZE(alc260_modes),
6991 .channel_mode = alc260_modes,
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +02006992 .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
6993 .input_mux = alc260_test_capture_sources,
Jonathan Woithe7cf51e42006-02-09 12:01:26 +01006994 },
6995#endif
Kailang Yangdf694da2005-12-05 19:42:22 +01006996};
6997
Linus Torvalds1da177e2005-04-16 15:20:36 -07006998static int patch_alc260(struct hda_codec *codec)
6999{
7000 struct alc_spec *spec;
Kailang Yangdf694da2005-12-05 19:42:22 +01007001 int err, board_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007002
Takashi Iwaie560d8d2005-09-09 14:21:46 +02007003 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007004 if (spec == NULL)
7005 return -ENOMEM;
7006
7007 codec->spec = spec;
7008
Takashi Iwaif5fcc132006-11-24 17:07:44 +01007009 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
7010 alc260_models,
7011 alc260_cfg_tbl);
7012 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +02007013 snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
Takashi Iwai6c627f32009-05-18 12:33:36 +02007014 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +01007015 board_config = ALC260_AUTO;
Takashi Iwai16ded522005-06-10 19:58:24 +02007016 }
7017
Takashi Iwaifc091762010-08-04 23:53:36 +02007018 if (board_config == ALC260_AUTO)
7019 alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 1);
7020
Kailang Yangdf694da2005-12-05 19:42:22 +01007021 if (board_config == ALC260_AUTO) {
7022 /* automatic parse from the BIOS config */
7023 err = alc260_parse_auto_config(codec);
7024 if (err < 0) {
7025 alc_free(codec);
7026 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02007027 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +02007028 printk(KERN_INFO
7029 "hda_codec: Cannot set up configuration "
7030 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +01007031 board_config = ALC260_BASIC;
7032 }
Takashi Iwai16ded522005-06-10 19:58:24 +02007033 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034
Kusanagi Kouichi680cd532009-02-05 00:00:58 +09007035 err = snd_hda_attach_beep_device(codec, 0x1);
7036 if (err < 0) {
7037 alc_free(codec);
7038 return err;
7039 }
7040
Kailang Yangdf694da2005-12-05 19:42:22 +01007041 if (board_config != ALC260_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +02007042 setup_preset(codec, &alc260_presets[board_config]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007043
Linus Torvalds1da177e2005-04-16 15:20:36 -07007044 spec->stream_analog_playback = &alc260_pcm_analog_playback;
7045 spec->stream_analog_capture = &alc260_pcm_analog_capture;
Jonathan Woithe53bacfb2010-08-08 00:17:05 +09307046 spec->stream_analog_alt_capture = &alc260_pcm_analog_capture;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007047
Takashi Iwaia3bcba32005-12-06 19:05:29 +01007048 spec->stream_digital_playback = &alc260_pcm_digital_playback;
7049 spec->stream_digital_capture = &alc260_pcm_digital_capture;
7050
Takashi Iwai4ef0ef12008-11-03 17:47:49 +01007051 if (!spec->adc_nids && spec->input_mux) {
7052 /* check whether NID 0x04 is valid */
7053 unsigned int wcap = get_wcaps(codec, 0x04);
Takashi Iwaia22d5432009-07-27 12:54:26 +02007054 wcap = get_wcaps_type(wcap);
Takashi Iwai4ef0ef12008-11-03 17:47:49 +01007055 /* get type */
7056 if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
7057 spec->adc_nids = alc260_adc_nids_alt;
7058 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
7059 } else {
7060 spec->adc_nids = alc260_adc_nids;
7061 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
7062 }
7063 }
Takashi Iwaib59bdf32009-08-11 09:47:30 +02007064 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01007065 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
Takashi Iwaif9e336f2008-10-31 16:37:07 +01007066
Takashi Iwaifc091762010-08-04 23:53:36 +02007067 if (board_config == ALC260_AUTO)
7068 alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 0);
7069
Takashi Iwai2134ea42008-01-10 16:53:55 +01007070 spec->vmaster_nid = 0x08;
7071
Linus Torvalds1da177e2005-04-16 15:20:36 -07007072 codec->patch_ops = alc_patch_ops;
Kailang Yangdf694da2005-12-05 19:42:22 +01007073 if (board_config == ALC260_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +01007074 spec->init_hook = alc260_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +02007075#ifdef CONFIG_SND_HDA_POWER_SAVE
7076 if (!spec->loopback.amplist)
7077 spec->loopback.amplist = alc260_loopbacks;
7078#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007079
7080 return 0;
7081}
7082
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007083
Linus Torvalds1da177e2005-04-16 15:20:36 -07007084/*
Takashi Iwai49535502009-06-30 15:28:30 +02007085 * ALC882/883/885/888/889 support
Linus Torvalds1da177e2005-04-16 15:20:36 -07007086 *
7087 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
7088 * configuration. Each pin widget can choose any input DACs and a mixer.
7089 * Each ADC is connected from a mixer of all inputs. This makes possible
7090 * 6-channel independent captures.
7091 *
7092 * In addition, an independent DAC for the multi-playback (not used in this
7093 * driver yet).
7094 */
Kailang Yangdf694da2005-12-05 19:42:22 +01007095#define ALC882_DIGOUT_NID 0x06
7096#define ALC882_DIGIN_NID 0x0a
Takashi Iwai49535502009-06-30 15:28:30 +02007097#define ALC883_DIGOUT_NID ALC882_DIGOUT_NID
7098#define ALC883_DIGIN_NID ALC882_DIGIN_NID
7099#define ALC1200_DIGOUT_NID 0x10
7100
Linus Torvalds1da177e2005-04-16 15:20:36 -07007101
Takashi Iwaid2a6d7d2005-11-17 11:06:29 +01007102static struct hda_channel_mode alc882_ch_modes[1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007103 { 8, NULL }
7104};
7105
Takashi Iwai49535502009-06-30 15:28:30 +02007106/* DACs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007107static hda_nid_t alc882_dac_nids[4] = {
7108 /* front, rear, clfe, rear_surr */
7109 0x02, 0x03, 0x04, 0x05
7110};
Takashi Iwai49535502009-06-30 15:28:30 +02007111#define alc883_dac_nids alc882_dac_nids
Linus Torvalds1da177e2005-04-16 15:20:36 -07007112
Takashi Iwai49535502009-06-30 15:28:30 +02007113/* ADCs */
Kailang Yangdf694da2005-12-05 19:42:22 +01007114#define alc882_adc_nids alc880_adc_nids
7115#define alc882_adc_nids_alt alc880_adc_nids_alt
Takashi Iwai49535502009-06-30 15:28:30 +02007116#define alc883_adc_nids alc882_adc_nids_alt
7117static hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
7118static hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
7119#define alc889_adc_nids alc880_adc_nids
Linus Torvalds1da177e2005-04-16 15:20:36 -07007120
Takashi Iwaie1406342008-02-11 18:32:32 +01007121static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
7122static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
Takashi Iwai49535502009-06-30 15:28:30 +02007123#define alc883_capsrc_nids alc882_capsrc_nids_alt
7124static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
7125#define alc889_capsrc_nids alc882_capsrc_nids
Takashi Iwaie1406342008-02-11 18:32:32 +01007126
Linus Torvalds1da177e2005-04-16 15:20:36 -07007127/* input MUX */
7128/* FIXME: should be a matrix-type input source selection */
7129
7130static struct hda_input_mux alc882_capture_source = {
7131 .num_items = 4,
7132 .items = {
7133 { "Mic", 0x0 },
7134 { "Front Mic", 0x1 },
7135 { "Line", 0x2 },
7136 { "CD", 0x4 },
7137 },
7138};
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007139
Takashi Iwai49535502009-06-30 15:28:30 +02007140#define alc883_capture_source alc882_capture_source
7141
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007142static struct hda_input_mux alc889_capture_source = {
7143 .num_items = 3,
7144 .items = {
7145 { "Front Mic", 0x0 },
7146 { "Mic", 0x3 },
7147 { "Line", 0x2 },
7148 },
7149};
7150
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007151static struct hda_input_mux mb5_capture_source = {
7152 .num_items = 3,
7153 .items = {
7154 { "Mic", 0x1 },
Alex Murrayb8f171e2010-06-14 12:08:43 +09307155 { "Line", 0x7 },
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007156 { "CD", 0x4 },
7157 },
7158};
7159
Luke Yelaviche458b1f2010-02-12 16:28:29 +11007160static struct hda_input_mux macmini3_capture_source = {
7161 .num_items = 2,
7162 .items = {
7163 { "Line", 0x2 },
7164 { "CD", 0x4 },
7165 },
7166};
7167
Takashi Iwai49535502009-06-30 15:28:30 +02007168static struct hda_input_mux alc883_3stack_6ch_intel = {
7169 .num_items = 4,
7170 .items = {
7171 { "Mic", 0x1 },
7172 { "Front Mic", 0x0 },
7173 { "Line", 0x2 },
7174 { "CD", 0x4 },
7175 },
7176};
7177
7178static struct hda_input_mux alc883_lenovo_101e_capture_source = {
7179 .num_items = 2,
7180 .items = {
7181 { "Mic", 0x1 },
7182 { "Line", 0x2 },
7183 },
7184};
7185
7186static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
7187 .num_items = 4,
7188 .items = {
7189 { "Mic", 0x0 },
David Henningsson150b4322010-07-29 14:46:42 +02007190 { "Int Mic", 0x1 },
Takashi Iwai49535502009-06-30 15:28:30 +02007191 { "Line", 0x2 },
7192 { "CD", 0x4 },
7193 },
7194};
7195
7196static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
7197 .num_items = 2,
7198 .items = {
7199 { "Mic", 0x0 },
7200 { "Int Mic", 0x1 },
7201 },
7202};
7203
7204static struct hda_input_mux alc883_lenovo_sky_capture_source = {
7205 .num_items = 3,
7206 .items = {
7207 { "Mic", 0x0 },
7208 { "Front Mic", 0x1 },
7209 { "Line", 0x4 },
7210 },
7211};
7212
7213static struct hda_input_mux alc883_asus_eee1601_capture_source = {
7214 .num_items = 2,
7215 .items = {
7216 { "Mic", 0x0 },
7217 { "Line", 0x2 },
7218 },
7219};
7220
7221static struct hda_input_mux alc889A_mb31_capture_source = {
7222 .num_items = 2,
7223 .items = {
7224 { "Mic", 0x0 },
7225 /* Front Mic (0x01) unused */
7226 { "Line", 0x2 },
7227 /* Line 2 (0x03) unused */
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02007228 /* CD (0x04) unused? */
Takashi Iwai49535502009-06-30 15:28:30 +02007229 },
7230};
7231
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07007232static struct hda_input_mux alc889A_imac91_capture_source = {
7233 .num_items = 2,
7234 .items = {
7235 { "Mic", 0x01 },
7236 { "Line", 0x2 }, /* Not sure! */
7237 },
7238};
7239
Takashi Iwai49535502009-06-30 15:28:30 +02007240/*
7241 * 2ch mode
7242 */
7243static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
7244 { 2, NULL }
7245};
7246
Kailang Yangdf694da2005-12-05 19:42:22 +01007247/*
Kailang Yang272a5272007-05-14 11:00:38 +02007248 * 2ch mode
7249 */
7250static struct hda_verb alc882_3ST_ch2_init[] = {
7251 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7252 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7253 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7254 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7255 { } /* end */
7256};
7257
7258/*
Takashi Iwai49535502009-06-30 15:28:30 +02007259 * 4ch mode
7260 */
7261static struct hda_verb alc882_3ST_ch4_init[] = {
7262 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7263 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7264 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7265 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7266 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7267 { } /* end */
7268};
7269
7270/*
Kailang Yang272a5272007-05-14 11:00:38 +02007271 * 6ch mode
7272 */
7273static struct hda_verb alc882_3ST_ch6_init[] = {
7274 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7275 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7276 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7277 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7278 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7279 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7280 { } /* end */
7281};
7282
Takashi Iwai49535502009-06-30 15:28:30 +02007283static struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
Kailang Yang272a5272007-05-14 11:00:38 +02007284 { 2, alc882_3ST_ch2_init },
Takashi Iwai49535502009-06-30 15:28:30 +02007285 { 4, alc882_3ST_ch4_init },
Kailang Yang272a5272007-05-14 11:00:38 +02007286 { 6, alc882_3ST_ch6_init },
7287};
7288
Takashi Iwai49535502009-06-30 15:28:30 +02007289#define alc883_3ST_6ch_modes alc882_3ST_6ch_modes
7290
Kailang Yang272a5272007-05-14 11:00:38 +02007291/*
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04307292 * 2ch mode
7293 */
7294static struct hda_verb alc883_3ST_ch2_clevo_init[] = {
7295 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
7296 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7297 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7298 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7299 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7300 { } /* end */
7301};
7302
7303/*
7304 * 4ch mode
7305 */
7306static struct hda_verb alc883_3ST_ch4_clevo_init[] = {
7307 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7308 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7309 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7310 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7311 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7312 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7313 { } /* end */
7314};
7315
7316/*
7317 * 6ch mode
7318 */
7319static struct hda_verb alc883_3ST_ch6_clevo_init[] = {
7320 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7321 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7322 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7323 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7324 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7325 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7326 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7327 { } /* end */
7328};
7329
7330static struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
7331 { 2, alc883_3ST_ch2_clevo_init },
7332 { 4, alc883_3ST_ch4_clevo_init },
7333 { 6, alc883_3ST_ch6_clevo_init },
7334};
7335
7336
7337/*
Kailang Yangdf694da2005-12-05 19:42:22 +01007338 * 6ch mode
7339 */
7340static struct hda_verb alc882_sixstack_ch6_init[] = {
7341 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7342 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7343 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7344 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7345 { } /* end */
7346};
7347
7348/*
7349 * 8ch mode
7350 */
7351static struct hda_verb alc882_sixstack_ch8_init[] = {
7352 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7353 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7354 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7355 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7356 { } /* end */
7357};
7358
7359static struct hda_channel_mode alc882_sixstack_modes[2] = {
7360 { 6, alc882_sixstack_ch6_init },
7361 { 8, alc882_sixstack_ch8_init },
7362};
7363
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08007364
7365/* Macbook Air 2,1 */
7366
7367static struct hda_channel_mode alc885_mba21_ch_modes[1] = {
7368 { 2, NULL },
7369};
7370
Takashi Iwai87350ad2007-08-16 18:19:38 +02007371/*
Sasha Alexandrdef319f2009-06-16 16:00:15 -04007372 * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
Takashi Iwai87350ad2007-08-16 18:19:38 +02007373 */
7374
7375/*
7376 * 2ch mode
7377 */
7378static struct hda_verb alc885_mbp_ch2_init[] = {
7379 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7380 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7381 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7382 { } /* end */
7383};
7384
7385/*
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007386 * 4ch mode
Takashi Iwai87350ad2007-08-16 18:19:38 +02007387 */
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007388static struct hda_verb alc885_mbp_ch4_init[] = {
Takashi Iwai87350ad2007-08-16 18:19:38 +02007389 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7390 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7391 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7392 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7393 { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7394 { } /* end */
7395};
7396
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007397static struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
Takashi Iwai87350ad2007-08-16 18:19:38 +02007398 { 2, alc885_mbp_ch2_init },
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007399 { 4, alc885_mbp_ch4_init },
Takashi Iwai87350ad2007-08-16 18:19:38 +02007400};
7401
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007402/*
7403 * 2ch
7404 * Speakers/Woofer/HP = Front
7405 * LineIn = Input
7406 */
7407static struct hda_verb alc885_mb5_ch2_init[] = {
7408 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7409 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7410 { } /* end */
7411};
7412
7413/*
7414 * 6ch mode
7415 * Speakers/HP = Front
7416 * Woofer = LFE
7417 * LineIn = Surround
7418 */
7419static struct hda_verb alc885_mb5_ch6_init[] = {
7420 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7421 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7422 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
7423 { } /* end */
7424};
7425
7426static struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
7427 { 2, alc885_mb5_ch2_init },
7428 { 6, alc885_mb5_ch6_init },
7429};
Takashi Iwai87350ad2007-08-16 18:19:38 +02007430
Takashi Iwaid01aecd2010-02-23 08:07:15 +01007431#define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes
Takashi Iwai49535502009-06-30 15:28:30 +02007432
7433/*
7434 * 2ch mode
7435 */
7436static struct hda_verb alc883_4ST_ch2_init[] = {
7437 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7438 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7439 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7440 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7441 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7442 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7443 { } /* end */
7444};
7445
7446/*
7447 * 4ch mode
7448 */
7449static struct hda_verb alc883_4ST_ch4_init[] = {
7450 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7451 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7452 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7453 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7454 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7455 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7456 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7457 { } /* end */
7458};
7459
7460/*
7461 * 6ch mode
7462 */
7463static struct hda_verb alc883_4ST_ch6_init[] = {
7464 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7465 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7466 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7467 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7468 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7469 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7470 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7471 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7472 { } /* end */
7473};
7474
7475/*
7476 * 8ch mode
7477 */
7478static struct hda_verb alc883_4ST_ch8_init[] = {
7479 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7480 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7481 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7482 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7483 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7484 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
7485 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7486 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7487 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7488 { } /* end */
7489};
7490
7491static struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
7492 { 2, alc883_4ST_ch2_init },
7493 { 4, alc883_4ST_ch4_init },
7494 { 6, alc883_4ST_ch6_init },
7495 { 8, alc883_4ST_ch8_init },
7496};
7497
7498
7499/*
7500 * 2ch mode
7501 */
7502static struct hda_verb alc883_3ST_ch2_intel_init[] = {
7503 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7504 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7505 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7506 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7507 { } /* end */
7508};
7509
7510/*
7511 * 4ch mode
7512 */
7513static struct hda_verb alc883_3ST_ch4_intel_init[] = {
7514 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
7515 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7516 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7517 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7518 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7519 { } /* end */
7520};
7521
7522/*
7523 * 6ch mode
7524 */
7525static struct hda_verb alc883_3ST_ch6_intel_init[] = {
7526 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7527 { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7528 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
7529 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7530 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
7531 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
7532 { } /* end */
7533};
7534
7535static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
7536 { 2, alc883_3ST_ch2_intel_init },
7537 { 4, alc883_3ST_ch4_intel_init },
7538 { 6, alc883_3ST_ch6_intel_init },
7539};
7540
7541/*
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007542 * 2ch mode
7543 */
7544static struct hda_verb alc889_ch2_intel_init[] = {
7545 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7546 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
7547 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
7548 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
7549 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
7550 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7551 { } /* end */
7552};
7553
7554/*
Takashi Iwai49535502009-06-30 15:28:30 +02007555 * 6ch mode
7556 */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007557static struct hda_verb alc889_ch6_intel_init[] = {
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007558 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7559 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
7560 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
7561 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7562 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007563 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
7564 { } /* end */
7565};
7566
7567/*
7568 * 8ch mode
7569 */
7570static struct hda_verb alc889_ch8_intel_init[] = {
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007571 { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
7572 { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
7573 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
7574 { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
7575 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007576 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7577 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007578 { } /* end */
7579};
7580
Wu Fengguangdd7714c2009-07-30 14:36:35 +08007581static struct hda_channel_mode alc889_8ch_intel_modes[3] = {
7582 { 2, alc889_ch2_intel_init },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007583 { 6, alc889_ch6_intel_init },
7584 { 8, alc889_ch8_intel_init },
7585};
7586
7587/*
7588 * 6ch mode
7589 */
Takashi Iwai49535502009-06-30 15:28:30 +02007590static struct hda_verb alc883_sixstack_ch6_init[] = {
7591 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
7592 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7593 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7594 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7595 { } /* end */
7596};
7597
7598/*
7599 * 8ch mode
7600 */
7601static struct hda_verb alc883_sixstack_ch8_init[] = {
7602 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7603 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7604 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7605 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
7606 { } /* end */
7607};
7608
7609static struct hda_channel_mode alc883_sixstack_modes[2] = {
7610 { 6, alc883_sixstack_ch6_init },
7611 { 8, alc883_sixstack_ch8_init },
7612};
7613
7614
Linus Torvalds1da177e2005-04-16 15:20:36 -07007615/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
7616 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
7617 */
Takashi Iwaic8b6bf9b2005-11-17 14:57:47 +01007618static struct snd_kcontrol_new alc882_base_mixer[] = {
Takashi Iwai05acb862005-06-10 19:50:25 +02007619 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007620 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007621 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007622 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007623 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
7624 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007625 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
7626 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Takashi Iwai05acb862005-06-10 19:50:25 +02007627 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Takashi Iwai985be542005-11-02 18:26:49 +01007628 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007629 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7630 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7631 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7632 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7633 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7634 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01007635 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007636 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
7637 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01007638 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007639 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007640 { } /* end */
7641};
7642
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08007643/* Macbook Air 2,1 same control for HP and internal Speaker */
7644
7645static struct snd_kcontrol_new alc885_mba21_mixer[] = {
7646 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7647 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
7648 { }
7649};
7650
7651
Takashi Iwai87350ad2007-08-16 18:19:38 +02007652static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
Takashi Iwaia3f730a2009-08-31 08:15:26 +02007653 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7654 HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
7655 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7656 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
7657 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01007658 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7659 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwai87350ad2007-08-16 18:19:38 +02007660 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
7661 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
Takashi Iwai2134ea42008-01-10 16:53:55 +01007662 HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
Takashi Iwai87350ad2007-08-16 18:19:38 +02007663 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
7664 { } /* end */
7665};
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007666
7667static struct snd_kcontrol_new alc885_mb5_mixer[] = {
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007668 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7669 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
7670 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
7671 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
7672 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7673 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
Alex Murraya76221d2010-01-13 23:15:03 +10307674 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
7675 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
Alex Murrayb8f171e2010-06-14 12:08:43 +09307676 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
7677 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
Kacper Szczesniak41d55452009-05-07 12:47:43 +02007678 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
7679 HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
7680 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
7681 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0x00, HDA_INPUT),
7682 { } /* end */
7683};
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02007684
Luke Yelaviche458b1f2010-02-12 16:28:29 +11007685static struct snd_kcontrol_new alc885_macmini3_mixer[] = {
7686 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7687 HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
7688 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
7689 HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
7690 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
7691 HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
7692 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
7693 HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
7694 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
7695 HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
7696 HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
7697 { } /* end */
7698};
7699
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08007700static struct snd_kcontrol_new alc885_imac91_mixer[] = {
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07007701 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
7702 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08007703 { } /* end */
7704};
7705
7706
Kailang Yangbdd148a2007-05-08 15:19:08 +02007707static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
7708 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7709 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7710 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7711 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7712 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7713 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7714 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7715 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7716 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangbdd148a2007-05-08 15:19:08 +02007717 { } /* end */
7718};
7719
Kailang Yang272a5272007-05-14 11:00:38 +02007720static struct snd_kcontrol_new alc882_targa_mixer[] = {
7721 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7722 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7723 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
7724 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7725 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7726 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7727 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7728 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7729 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai96fe7cc2007-09-07 10:57:44 +02007730 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007731 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
7732 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai96fe7cc2007-09-07 10:57:44 +02007733 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007734 { } /* end */
7735};
7736
7737/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
7738 * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
7739 */
7740static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
7741 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7742 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7743 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7744 HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
7745 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7746 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7747 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7748 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7749 HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
7750 HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
7751 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7752 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai96fe7cc2007-09-07 10:57:44 +02007753 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02007754 { } /* end */
7755};
7756
Takashi Iwai914759b2007-09-06 14:52:04 +02007757static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
7758 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7759 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7760 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7761 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
7762 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
7763 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
7764 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
7765 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
7766 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
7767 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai914759b2007-09-06 14:52:04 +02007768 { } /* end */
7769};
7770
Kailang Yangdf694da2005-12-05 19:42:22 +01007771static struct snd_kcontrol_new alc882_chmode_mixer[] = {
7772 {
7773 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7774 .name = "Channel Mode",
7775 .info = alc_ch_mode_info,
7776 .get = alc_ch_mode_get,
7777 .put = alc_ch_mode_put,
7778 },
7779 { } /* end */
7780};
7781
Takashi Iwai49535502009-06-30 15:28:30 +02007782static struct hda_verb alc882_base_init_verbs[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007783 /* Front mixer: unmute input/output amp left and right (volume = 0) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007784 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7785 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007786 /* Rear mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007787 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7788 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007789 /* CLFE mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007790 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7791 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007792 /* Side mixer */
Takashi Iwai05acb862005-06-10 19:50:25 +02007793 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7794 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007795
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007796 /* Front Pin: output 0 (0x0c) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007797 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007798 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007799 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007800 /* Rear Pin: output 1 (0x0d) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007801 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007802 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007803 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007804 /* CLFE Pin: output 2 (0x0e) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007805 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007806 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007807 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007808 /* Side Pin: output 3 (0x0f) */
Takashi Iwai05acb862005-06-10 19:50:25 +02007809 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai05acb862005-06-10 19:50:25 +02007810 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007811 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007812 /* Mic (rear) pin: input vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02007813 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007814 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7815 /* Front Mic pin: input vref at 80% */
Takashi Iwai16ded522005-06-10 19:58:24 +02007816 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007817 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7818 /* Line In pin: input */
Takashi Iwai05acb862005-06-10 19:50:25 +02007819 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaie9edcee2005-06-13 14:16:38 +02007820 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7821 /* Line-2 In: Headphone output (output 0 - 0x0c) */
7822 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7823 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7824 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007825 /* CD pin widget for input */
Takashi Iwai05acb862005-06-10 19:50:25 +02007826 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007827
7828 /* FIXME: use matrix-type input source selection */
7829 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007830 /* Input mixer2 */
Takashi Iwai05acb862005-06-10 19:50:25 +02007831 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007832 /* Input mixer3 */
Takashi Iwai05acb862005-06-10 19:50:25 +02007833 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Takashi Iwai05acb862005-06-10 19:50:25 +02007834 /* ADC2: mute amp left and right */
7835 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02007836 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwai05acb862005-06-10 19:50:25 +02007837 /* ADC3: mute amp left and right */
7838 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Takashi Iwai71fe7b82005-05-25 18:11:40 +02007839 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Linus Torvalds1da177e2005-04-16 15:20:36 -07007840
7841 { }
7842};
7843
Takashi Iwai49535502009-06-30 15:28:30 +02007844static struct hda_verb alc882_adc1_init_verbs[] = {
7845 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7846 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7847 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7848 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7849 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7850 /* ADC1: mute amp left and right */
7851 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7852 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
7853 { }
7854};
7855
Takashi Iwai4b146cb2006-07-28 14:42:36 +02007856static struct hda_verb alc882_eapd_verbs[] = {
7857 /* change to EAPD mode */
7858 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01007859 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02007860 { }
Takashi Iwai4b146cb2006-07-28 14:42:36 +02007861};
7862
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007863static struct hda_verb alc889_eapd_verbs[] = {
7864 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
7865 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
7866 { }
7867};
7868
Wu Fengguang6732bd02009-07-30 09:19:14 +02007869static struct hda_verb alc_hp15_unsol_verbs[] = {
7870 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
7871 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7872 {}
7873};
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007874
7875static struct hda_verb alc885_init_verbs[] = {
7876 /* Front mixer: unmute input/output amp left and right (volume = 0) */
Kailang Yang88102f32010-02-04 14:12:58 +01007877 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7878 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007879 /* Rear mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007880 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7881 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007882 /* CLFE mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007883 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7884 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007885 /* Side mixer */
Kailang Yang88102f32010-02-04 14:12:58 +01007886 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7887 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007888
7889 /* Front HP Pin: output 0 (0x0c) */
Wu Fengguang6732bd02009-07-30 09:19:14 +02007890 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007891 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7892 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7893 /* Front Pin: output 0 (0x0c) */
7894 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7895 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7896 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
7897 /* Rear Pin: output 1 (0x0d) */
7898 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7899 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7900 {0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
7901 /* CLFE Pin: output 2 (0x0e) */
7902 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7903 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7904 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
7905 /* Side Pin: output 3 (0x0f) */
7906 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7907 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7908 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
7909 /* Mic (rear) pin: input vref at 80% */
7910 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7911 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7912 /* Front Mic pin: input vref at 80% */
7913 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7914 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7915 /* Line In pin: input */
7916 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
7917 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7918
7919 /* Mixer elements: 0x18, , 0x1a, 0x1b */
7920 /* Input mixer1 */
Kailang Yang88102f32010-02-04 14:12:58 +01007921 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007922 /* Input mixer2 */
7923 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007924 /* Input mixer3 */
Kailang Yang88102f32010-02-04 14:12:58 +01007925 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02007926 /* ADC2: mute amp left and right */
7927 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7928 /* ADC3: mute amp left and right */
7929 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7930
7931 { }
7932};
7933
7934static struct hda_verb alc885_init_input_verbs[] = {
7935 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7936 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7937 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
7938 { }
7939};
7940
7941
7942/* Unmute Selector 24h and set the default input to front mic */
7943static struct hda_verb alc889_init_input_verbs[] = {
7944 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
7945 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7946 { }
7947};
7948
7949
Takashi Iwai49535502009-06-30 15:28:30 +02007950#define alc883_init_verbs alc882_base_init_verbs
7951
Tobin Davis9102cd12006-12-15 10:02:12 +01007952/* Mac Pro test */
7953static struct snd_kcontrol_new alc882_macpro_mixer[] = {
7954 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
7955 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
7956 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
7957 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
7958 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01007959 /* FIXME: this looks suspicious...
Jaroslav Kyselad355c82a2009-11-03 15:47:25 +01007960 HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
7961 HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +01007962 */
Tobin Davis9102cd12006-12-15 10:02:12 +01007963 { } /* end */
7964};
7965
7966static struct hda_verb alc882_macpro_init_verbs[] = {
7967 /* Front mixer: unmute input/output amp left and right (volume = 0) */
7968 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7969 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
7970 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
7971 /* Front Pin: output 0 (0x0c) */
7972 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7973 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7974 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
7975 /* Front Mic pin: input vref at 80% */
7976 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
7977 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7978 /* Speaker: output */
7979 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
7980 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7981 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
7982 /* Headphone output (output 0 - 0x0c) */
7983 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
7984 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7985 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
7986
7987 /* FIXME: use matrix-type input source selection */
7988 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
7989 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7990 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7991 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7992 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7993 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7994 /* Input mixer2 */
7995 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7996 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
7997 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
7998 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
7999 /* Input mixer3 */
8000 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8001 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8002 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8003 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8004 /* ADC1: mute amp left and right */
8005 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8006 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8007 /* ADC2: mute amp left and right */
8008 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8009 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8010 /* ADC3: mute amp left and right */
8011 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8012 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8013
8014 { }
8015};
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008016
Kacper Szczesniak41d55452009-05-07 12:47:43 +02008017/* Macbook 5,1 */
8018static struct hda_verb alc885_mb5_init_verbs[] = {
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02008019 /* DACs */
8020 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8021 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8022 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8023 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak41d55452009-05-07 12:47:43 +02008024 /* Front mixer */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02008025 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8026 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8027 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02008028 /* Surround mixer */
8029 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8030 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8031 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8032 /* LFE mixer */
8033 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8034 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8035 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8036 /* HP mixer */
8037 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8038 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8039 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8040 /* Front Pin (0x0c) */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02008041 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8042 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02008043 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8044 /* LFE Pin (0x0e) */
8045 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8046 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8047 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
8048 /* HP Pin (0x0f) */
Kacper Szczesniak41d55452009-05-07 12:47:43 +02008049 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8050 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kacper Szczesniak92b9de82009-06-02 00:55:19 +02008051 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
Alex Murraya76221d2010-01-13 23:15:03 +10308052 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kacper Szczesniak41d55452009-05-07 12:47:43 +02008053 /* Front Mic pin: input vref at 80% */
8054 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8055 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8056 /* Line In pin */
8057 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8058 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8059
Alex Murrayb8f171e2010-06-14 12:08:43 +09308060 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
8061 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
8062 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
Kacper Szczesniak41d55452009-05-07 12:47:43 +02008063 { }
8064};
8065
Luke Yelaviche458b1f2010-02-12 16:28:29 +11008066/* Macmini 3,1 */
8067static struct hda_verb alc885_macmini3_init_verbs[] = {
8068 /* DACs */
8069 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8070 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8071 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8072 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8073 /* Front mixer */
8074 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8075 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8076 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8077 /* Surround mixer */
8078 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8079 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8080 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8081 /* LFE mixer */
8082 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8083 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8084 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8085 /* HP mixer */
8086 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8087 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8088 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8089 /* Front Pin (0x0c) */
8090 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8091 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8092 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8093 /* LFE Pin (0x0e) */
8094 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
8095 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8096 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
8097 /* HP Pin (0x0f) */
8098 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8099 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8100 {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
8101 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8102 /* Line In pin */
8103 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8104 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8105
8106 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8107 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8108 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8109 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8110 { }
8111};
8112
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08008113
8114static struct hda_verb alc885_mba21_init_verbs[] = {
8115 /*Internal and HP Speaker Mixer*/
8116 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8117 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8118 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8119 /*Internal Speaker Pin (0x0c)*/
8120 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8121 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8122 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8123 /* HP Pin: output 0 (0x0e) */
8124 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
8125 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8126 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8127 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
8128 /* Line in (is hp when jack connected)*/
8129 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
8130 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8131
8132 { }
8133 };
8134
8135
Takashi Iwai87350ad2007-08-16 18:19:38 +02008136/* Macbook Pro rev3 */
8137static struct hda_verb alc885_mbp3_init_verbs[] = {
8138 /* Front mixer: unmute input/output amp left and right (volume = 0) */
8139 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8140 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8141 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8142 /* Rear mixer */
8143 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8144 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8145 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwaia3f730a2009-08-31 08:15:26 +02008146 /* HP mixer */
8147 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8148 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8149 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai87350ad2007-08-16 18:19:38 +02008150 /* Front Pin: output 0 (0x0c) */
8151 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8152 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8153 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
Takashi Iwaia3f730a2009-08-31 08:15:26 +02008154 /* HP Pin: output 0 (0x0e) */
Takashi Iwai87350ad2007-08-16 18:19:38 +02008155 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
Takashi Iwaia3f730a2009-08-31 08:15:26 +02008156 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8157 {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
Takashi Iwai87350ad2007-08-16 18:19:38 +02008158 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8159 /* Mic (rear) pin: input vref at 80% */
8160 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8161 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8162 /* Front Mic pin: input vref at 80% */
8163 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8164 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8165 /* Line In pin: use output 1 when in LineOut mode */
8166 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8167 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8168 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
8169
8170 /* FIXME: use matrix-type input source selection */
8171 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
8172 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
8173 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8174 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8175 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8176 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8177 /* Input mixer2 */
8178 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8179 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8180 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8181 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8182 /* Input mixer3 */
8183 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8184 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8185 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8186 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
8187 /* ADC1: mute amp left and right */
8188 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8189 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
8190 /* ADC2: mute amp left and right */
8191 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8192 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8193 /* ADC3: mute amp left and right */
8194 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8195 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8196
8197 { }
8198};
8199
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008200/* iMac 9,1 */
8201static struct hda_verb alc885_imac91_init_verbs[] = {
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07008202 /* Internal Speaker Pin (0x0c) */
8203 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8204 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8205 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8206 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
8207 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8208 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8209 /* HP Pin: Rear */
8210 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8211 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8212 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8213 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
8214 /* Line in Rear */
8215 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
8216 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8217 /* Front Mic pin: input vref at 80% */
8218 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8219 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008220 /* Rear mixer */
8221 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8222 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8223 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07008224 /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
8225 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8226 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8227 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8228 /* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008229 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8230 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8231 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8232 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07008233 /* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008234 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8235 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8236 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8237 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07008238 /* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008239 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8240 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
8241 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
8242 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07008243 /* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008244 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8245 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07008246 /* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008247 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8248 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07008249 /* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008250 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8251 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008252 { }
8253};
8254
Nicola Fagnanic54728d2007-07-19 23:28:52 +02008255/* iMac 24 mixer. */
8256static struct snd_kcontrol_new alc885_imac24_mixer[] = {
8257 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8258 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
8259 { } /* end */
8260};
8261
8262/* iMac 24 init verbs. */
8263static struct hda_verb alc885_imac24_init_verbs[] = {
8264 /* Internal speakers: output 0 (0x0c) */
8265 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8266 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8267 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
8268 /* Internal speakers: output 0 (0x0c) */
8269 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8270 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8271 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8272 /* Headphone: output 0 (0x0c) */
8273 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8274 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8275 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8276 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8277 /* Front Mic: input vref at 80% */
8278 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8279 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8280 { }
8281};
8282
8283/* Toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008284static void alc885_imac24_setup(struct hda_codec *codec)
Nicola Fagnanic54728d2007-07-19 23:28:52 +02008285{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008286 struct alc_spec *spec = codec->spec;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02008287
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008288 spec->autocfg.hp_pins[0] = 0x14;
8289 spec->autocfg.speaker_pins[0] = 0x18;
8290 spec->autocfg.speaker_pins[1] = 0x1a;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02008291}
8292
Takashi Iwai9d54f082010-02-22 08:34:40 +01008293#define alc885_mb5_setup alc885_imac24_setup
8294#define alc885_macmini3_setup alc885_imac24_setup
8295
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08008296/* Macbook Air 2,1 */
8297static void alc885_mba21_setup(struct hda_codec *codec)
8298{
8299 struct alc_spec *spec = codec->spec;
8300
8301 spec->autocfg.hp_pins[0] = 0x14;
8302 spec->autocfg.speaker_pins[0] = 0x18;
8303}
8304
8305
8306
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008307static void alc885_mbp3_setup(struct hda_codec *codec)
Nicola Fagnanic54728d2007-07-19 23:28:52 +02008308{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008309 struct alc_spec *spec = codec->spec;
Nicola Fagnanic54728d2007-07-19 23:28:52 +02008310
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008311 spec->autocfg.hp_pins[0] = 0x15;
8312 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai87350ad2007-08-16 18:19:38 +02008313}
8314
Takashi Iwai9d54f082010-02-22 08:34:40 +01008315static void alc885_imac91_setup(struct hda_codec *codec)
Alex Murraya76221d2010-01-13 23:15:03 +10308316{
Takashi Iwai9d54f082010-02-22 08:34:40 +01008317 struct alc_spec *spec = codec->spec;
Alex Murraya76221d2010-01-13 23:15:03 +10308318
Takashi Iwai9d54f082010-02-22 08:34:40 +01008319 spec->autocfg.hp_pins[0] = 0x14;
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07008320 spec->autocfg.speaker_pins[0] = 0x18;
Takashi Iwai9d54f082010-02-22 08:34:40 +01008321 spec->autocfg.speaker_pins[1] = 0x1a;
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08008322}
Takashi Iwai87350ad2007-08-16 18:19:38 +02008323
Kailang Yang272a5272007-05-14 11:00:38 +02008324static struct hda_verb alc882_targa_verbs[] = {
8325 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8326 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8327
8328 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8329 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02008330
Kailang Yang272a5272007-05-14 11:00:38 +02008331 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8332 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8333 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8334
8335 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yang272a5272007-05-14 11:00:38 +02008336 { } /* end */
8337};
8338
8339/* toggle speaker-output according to the hp-jack state */
8340static void alc882_targa_automute(struct hda_codec *codec)
8341{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008342 struct alc_spec *spec = codec->spec;
8343 alc_automute_amp(codec);
Takashi Iwai82beb8f2007-08-10 17:09:26 +02008344 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008345 spec->jack_present ? 1 : 3);
8346}
8347
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008348static void alc882_targa_setup(struct hda_codec *codec)
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008349{
8350 struct alc_spec *spec = codec->spec;
8351
8352 spec->autocfg.hp_pins[0] = 0x14;
8353 spec->autocfg.speaker_pins[0] = 0x1b;
Kailang Yang272a5272007-05-14 11:00:38 +02008354}
8355
8356static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
8357{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008358 if ((res >> 26) == ALC880_HP_EVENT)
Kailang Yang272a5272007-05-14 11:00:38 +02008359 alc882_targa_automute(codec);
Kailang Yang272a5272007-05-14 11:00:38 +02008360}
8361
8362static struct hda_verb alc882_asus_a7j_verbs[] = {
8363 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8364 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8365
8366 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8367 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8368 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02008369
Kailang Yang272a5272007-05-14 11:00:38 +02008370 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8371 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8372 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8373
8374 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8375 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8376 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8377 { } /* end */
8378};
8379
Takashi Iwai914759b2007-09-06 14:52:04 +02008380static struct hda_verb alc882_asus_a7m_verbs[] = {
8381 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8382 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8383
8384 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8385 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8386 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02008387
Takashi Iwai914759b2007-09-06 14:52:04 +02008388 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8389 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8390 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
8391
8392 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
8393 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
8394 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
8395 { } /* end */
8396};
8397
Tobin Davis9102cd12006-12-15 10:02:12 +01008398static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
8399{
8400 unsigned int gpiostate, gpiomask, gpiodir;
8401
8402 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
8403 AC_VERB_GET_GPIO_DATA, 0);
8404
8405 if (!muted)
8406 gpiostate |= (1 << pin);
8407 else
8408 gpiostate &= ~(1 << pin);
8409
8410 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
8411 AC_VERB_GET_GPIO_MASK, 0);
8412 gpiomask |= (1 << pin);
8413
8414 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
8415 AC_VERB_GET_GPIO_DIRECTION, 0);
8416 gpiodir |= (1 << pin);
8417
8418
8419 snd_hda_codec_write(codec, codec->afg, 0,
8420 AC_VERB_SET_GPIO_MASK, gpiomask);
8421 snd_hda_codec_write(codec, codec->afg, 0,
8422 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
8423
8424 msleep(1);
8425
8426 snd_hda_codec_write(codec, codec->afg, 0,
8427 AC_VERB_SET_GPIO_DATA, gpiostate);
8428}
8429
Takashi Iwai7debbe52007-08-16 15:01:03 +02008430/* set up GPIO at initialization */
8431static void alc885_macpro_init_hook(struct hda_codec *codec)
8432{
8433 alc882_gpio_mute(codec, 0, 0);
8434 alc882_gpio_mute(codec, 1, 0);
8435}
8436
8437/* set up GPIO and update auto-muting at initialization */
8438static void alc885_imac24_init_hook(struct hda_codec *codec)
8439{
8440 alc885_macpro_init_hook(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008441 alc_automute_amp(codec);
Takashi Iwai7debbe52007-08-16 15:01:03 +02008442}
8443
Kailang Yangdf694da2005-12-05 19:42:22 +01008444/*
8445 * generic initialization of ADC, input mixers and output mixers
8446 */
Takashi Iwai49535502009-06-30 15:28:30 +02008447static struct hda_verb alc883_auto_init_verbs[] = {
Kailang Yangdf694da2005-12-05 19:42:22 +01008448 /*
8449 * Unmute ADC0-2 and set the default input to mic-in
8450 */
Kailang Yangdf694da2005-12-05 19:42:22 +01008451 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
8452 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8453 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8454 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8455
Kailang Yangdf694da2005-12-05 19:42:22 +01008456 /*
8457 * Set up output mixers (0x0c - 0x0f)
8458 */
8459 /* set vol=0 to output mixers */
8460 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8461 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8462 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8463 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8464 /* set up input amps for analog loopback */
8465 /* Amp Indices: DAC = 0, mixer = 1 */
8466 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8467 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8468 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8469 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8470 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8471 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8472 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8473 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8474 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8475 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8476
8477 /* FIXME: use matrix-type input source selection */
8478 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
Kailang Yangdf694da2005-12-05 19:42:22 +01008479 /* Input mixer2 */
Kailang Yang88102f32010-02-04 14:12:58 +01008480 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangdf694da2005-12-05 19:42:22 +01008481 /* Input mixer3 */
Kailang Yang88102f32010-02-04 14:12:58 +01008482 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangdf694da2005-12-05 19:42:22 +01008483 { }
8484};
8485
Torben Schulzeb4c41d2009-05-18 15:02:35 +02008486/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
8487static struct hda_verb alc889A_mb31_ch2_init[] = {
8488 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
8489 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8490 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
8491 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
8492 { } /* end */
8493};
8494
8495/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
8496static struct hda_verb alc889A_mb31_ch4_init[] = {
8497 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
8498 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8499 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
8500 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
8501 { } /* end */
8502};
8503
8504/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
8505static struct hda_verb alc889A_mb31_ch5_init[] = {
8506 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */
8507 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
8508 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
8509 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
8510 { } /* end */
8511};
8512
8513/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
8514static struct hda_verb alc889A_mb31_ch6_init[] = {
8515 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */
8516 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */
8517 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
8518 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
8519 { } /* end */
8520};
8521
8522static struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
8523 { 2, alc889A_mb31_ch2_init },
8524 { 4, alc889A_mb31_ch4_init },
8525 { 5, alc889A_mb31_ch5_init },
8526 { 6, alc889A_mb31_ch6_init },
8527};
8528
Andrew L. Neporadab373bde2006-11-07 11:37:08 +01008529static struct hda_verb alc883_medion_eapd_verbs[] = {
8530 /* eanable EAPD on medion laptop */
8531 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
8532 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
8533 { }
8534};
8535
Takashi Iwai49535502009-06-30 15:28:30 +02008536#define alc883_base_mixer alc882_base_mixer
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008537
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008538static struct snd_kcontrol_new alc883_mitac_mixer[] = {
8539 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8540 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8541 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8542 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8543 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8544 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8545 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8546 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8547 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8548 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8549 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8550 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8551 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008552 { } /* end */
8553};
8554
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01008555static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
Jiang zhe368c7a92008-03-04 11:20:33 +01008556 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8557 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
8558 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8559 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
8560 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8561 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8562 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8563 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8564 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8565 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Jiang zhe368c7a92008-03-04 11:20:33 +01008566 { } /* end */
8567};
8568
Jiang zhefb97dc62008-03-06 11:07:11 +01008569static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
8570 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8571 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
8572 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8573 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
8574 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8575 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8576 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8577 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8578 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8579 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Jiang zhefb97dc62008-03-06 11:07:11 +01008580 { } /* end */
8581};
8582
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008583static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
8584 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8585 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8586 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8587 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8588 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8589 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8590 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8591 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008592 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008593 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8594 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008595 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008596 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008597 { } /* end */
8598};
8599
8600static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
8601 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8602 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8603 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8604 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8605 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8606 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8607 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8608 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8609 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8610 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8611 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8612 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8613 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8614 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008615 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008616 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8617 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008618 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008619 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008620 { } /* end */
8621};
8622
Jiang zhe17bba1b2008-06-04 12:11:07 +02008623static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
8624 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8625 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8626 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8627 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8628 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
8629 HDA_OUTPUT),
8630 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8631 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8632 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8633 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8634 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8635 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8636 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8637 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8638 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8639 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
8640 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8641 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8642 HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
8643 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Jiang zhe17bba1b2008-06-04 12:11:07 +02008644 { } /* end */
8645};
8646
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02008647static struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
8648 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8649 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8650 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8651 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8652 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
8653 HDA_OUTPUT),
8654 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8655 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8656 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8657 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8658 HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
8659 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8660 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8661 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8662 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
8663 HDA_CODEC_VOLUME("Mic Boost", 0x1b, 0, HDA_INPUT),
8664 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
8665 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8666 HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
8667 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8668 { } /* end */
8669};
8670
Takashi Iwaid1d985f2006-11-23 19:27:12 +01008671static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
Tobin Davisc07584c2006-10-13 12:32:16 +02008672 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008673 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008674 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008675 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008676 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8677 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
Takashi Iwai0701e062008-06-27 16:30:57 +02008678 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8679 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008680 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8681 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8682 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8683 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8684 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8685 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008686 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008687 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8688 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008689 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008690 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Tobin Davisc07584c2006-10-13 12:32:16 +02008691 { } /* end */
8692};
8693
Sasha Alexandrc2592492009-06-16 14:52:54 -04008694static struct snd_kcontrol_new alc883_targa_mixer[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02008695 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008696 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008697 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008698 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008699 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8700 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8701 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
8702 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
8703 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8704 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8705 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8706 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8707 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8708 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8709 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008710 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008711 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008712 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008713};
Kailang Yangccc656c2006-10-17 12:32:26 +02008714
Sasha Alexandrc2592492009-06-16 14:52:54 -04008715static struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02008716 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008717 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008718 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Takashi Iwaib99dba32009-09-17 18:23:00 +02008719 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008720 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8721 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8722 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
Thomas De Schampheleire32360412007-01-24 16:13:35 +01008723 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008724 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Jiang zhe4383fae2008-04-14 12:58:57 +02008725 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8726 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8727 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangccc656c2006-10-17 12:32:26 +02008728 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008729};
Kailang Yangccc656c2006-10-17 12:32:26 +02008730
Takashi Iwaib99dba32009-09-17 18:23:00 +02008731static struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
8732 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8733 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
8734 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8735 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
8736 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8737 { } /* end */
8738};
8739
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008740static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
8741 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8742 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +01008743 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
8744 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008745 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8746 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8747 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8748 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008749 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02008750};
Kailang Yangbc9f98a2007-04-12 13:06:07 +02008751
Kailang Yang272a5272007-05-14 11:00:38 +02008752static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
8753 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8754 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
8755 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8756 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8757 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8758 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8759 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
David Henningsson150b4322010-07-29 14:46:42 +02008760 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8761 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02008762 { } /* end */
8763};
8764
8765static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
8766 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8767 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8768 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8769 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8770 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8771 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8772 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8773 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8774 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +02008775 { } /* end */
Kailang Yangea1fb292008-08-26 12:58:38 +02008776};
Kailang Yang272a5272007-05-14 11:00:38 +02008777
Maurus Cuelenaere7ad7b212010-04-06 18:12:52 +02008778static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
8779 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8780 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8781 HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8782 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
8783 HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT),
8784 HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT),
8785 { } /* end */
8786};
8787
8788static struct hda_verb alc883_medion_wim2160_verbs[] = {
8789 /* Unmute front mixer */
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 /* Set speaker pin to front mixer */
8794 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8795
8796 /* Init headphone pin */
8797 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8798 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8799 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
8800 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8801
8802 { } /* end */
8803};
8804
8805/* toggle speaker-output according to the hp-jack state */
8806static void alc883_medion_wim2160_setup(struct hda_codec *codec)
8807{
8808 struct alc_spec *spec = codec->spec;
8809
8810 spec->autocfg.hp_pins[0] = 0x1a;
8811 spec->autocfg.speaker_pins[0] = 0x15;
8812}
8813
Tobin Davis2880a862007-08-07 11:50:26 +02008814static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
Kailang Yangd1a991a2007-08-15 16:21:59 +02008815 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8816 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008817 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008818 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8819 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Kailang Yangd1a991a2007-08-15 16:21:59 +02008820 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8821 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8822 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Tobin Davis2880a862007-08-07 11:50:26 +02008823 { } /* end */
Kailang Yangd1a991a2007-08-15 16:21:59 +02008824};
Tobin Davis2880a862007-08-07 11:50:26 +02008825
Tony Vroond2fd4b02009-06-21 00:40:10 +01008826static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
8827 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Tony Vroond2fd4b02009-06-21 00:40:10 +01008828 HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
Tony Vroon684a8842009-06-26 09:27:50 +01008829 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8830 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
Tony Vroond2fd4b02009-06-21 00:40:10 +01008831 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8832 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8833 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8834 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8835 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8836 { } /* end */
8837};
8838
Kailang Yange2757d52008-08-26 13:17:46 +02008839static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
8840 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8841 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8842 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
8843 HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
8844 HDA_CODEC_VOLUME_MONO("Center Playback Volume",
8845 0x0d, 1, 0x0, HDA_OUTPUT),
8846 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
8847 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
8848 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
8849 HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
8850 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
Kailang Yange2757d52008-08-26 13:17:46 +02008851 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8852 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8853 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8854 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8855 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8856 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8857 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8858 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8859 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8860 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yange2757d52008-08-26 13:17:46 +02008861 { } /* end */
8862};
8863
Torben Schulzeb4c41d2009-05-18 15:02:35 +02008864static struct snd_kcontrol_new alc889A_mb31_mixer[] = {
8865 /* Output mixers */
8866 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
8867 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
8868 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
8869 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
8870 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
8871 HDA_OUTPUT),
8872 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
8873 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
8874 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
8875 /* Output switches */
8876 HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
8877 HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
8878 HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
8879 /* Boost mixers */
8880 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
8881 HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
8882 /* Input mixers */
8883 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
8884 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
8885 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8886 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8887 { } /* end */
8888};
8889
Guido Günther3e1647c2009-06-05 00:47:26 +02008890static struct snd_kcontrol_new alc883_vaiott_mixer[] = {
8891 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8892 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8893 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
8894 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8895 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
8896 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8897 { } /* end */
8898};
8899
Kailang Yange2757d52008-08-26 13:17:46 +02008900static struct hda_bind_ctls alc883_bind_cap_vol = {
8901 .ops = &snd_hda_bind_vol,
8902 .values = {
8903 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
8904 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
8905 0
8906 },
8907};
8908
8909static struct hda_bind_ctls alc883_bind_cap_switch = {
8910 .ops = &snd_hda_bind_sw,
8911 .values = {
8912 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
8913 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
8914 0
8915 },
8916};
8917
8918static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
8919 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
8920 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8921 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
8922 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8923 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8924 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8925 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8926 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaif9e336f2008-10-31 16:37:07 +01008927 { } /* end */
8928};
8929
8930static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
Kailang Yange2757d52008-08-26 13:17:46 +02008931 HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
8932 HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
8933 {
8934 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8935 /* .name = "Capture Source", */
8936 .name = "Input Source",
8937 .count = 1,
Takashi Iwai54cbc9a2008-10-31 15:24:04 +01008938 .info = alc_mux_enum_info,
8939 .get = alc_mux_enum_get,
8940 .put = alc_mux_enum_put,
Kailang Yange2757d52008-08-26 13:17:46 +02008941 },
8942 { } /* end */
8943};
8944
Takashi Iwai9c7f8522006-06-28 15:08:22 +02008945static struct snd_kcontrol_new alc883_chmode_mixer[] = {
8946 {
8947 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8948 .name = "Channel Mode",
8949 .info = alc_ch_mode_info,
8950 .get = alc_ch_mode_get,
8951 .put = alc_ch_mode_put,
8952 },
8953 { } /* end */
8954};
8955
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008956/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02008957static void alc883_mitac_setup(struct hda_codec *codec)
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008958{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008959 struct alc_spec *spec = codec->spec;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008960
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02008961 spec->autocfg.hp_pins[0] = 0x15;
8962 spec->autocfg.speaker_pins[0] = 0x14;
8963 spec->autocfg.speaker_pins[1] = 0x17;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008964}
8965
8966/* auto-toggle front mic */
8967/*
8968static void alc883_mitac_mic_automute(struct hda_codec *codec)
8969{
Wu Fengguang864f92b2009-11-18 12:38:02 +08008970 unsigned char bits = snd_hda_jack_detect(codec, 0x18) ? HDA_AMP_MUTE : 0;
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008971
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008972 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
8973}
8974*/
8975
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01008976static struct hda_verb alc883_mitac_verbs[] = {
8977 /* HP */
8978 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8979 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8980 /* Subwoofer */
8981 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
8982 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8983
8984 /* enable unsolicited event */
8985 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
8986 /* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, */
8987
8988 { } /* end */
8989};
8990
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04308991static struct hda_verb alc883_clevo_m540r_verbs[] = {
8992 /* HP */
8993 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
8994 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8995 /* Int speaker */
8996 /*{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},*/
8997
8998 /* enable unsolicited event */
8999 /*
9000 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9001 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9002 */
9003
9004 { } /* end */
9005};
9006
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009007static struct hda_verb alc883_clevo_m720_verbs[] = {
Jiang zhe368c7a92008-03-04 11:20:33 +01009008 /* HP */
9009 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9010 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9011 /* Int speaker */
9012 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
9013 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9014
9015 /* enable unsolicited event */
9016 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009017 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
Jiang zhe368c7a92008-03-04 11:20:33 +01009018
9019 { } /* end */
9020};
9021
Jiang zhefb97dc62008-03-06 11:07:11 +01009022static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
9023 /* HP */
9024 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9025 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9026 /* Subwoofer */
9027 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
9028 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9029
9030 /* enable unsolicited event */
9031 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9032
9033 { } /* end */
9034};
9035
Sasha Alexandrc2592492009-06-16 14:52:54 -04009036static struct hda_verb alc883_targa_verbs[] = {
Kailang Yangccc656c2006-10-17 12:32:26 +02009037 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9038 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9039
9040 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9041 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangea1fb292008-08-26 12:58:38 +02009042
David Heidelberger64a8be72009-06-08 16:15:18 +02009043/* Connect Line-Out side jack (SPDIF) to Side */
9044 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9045 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9046 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
9047/* Connect Mic jack to CLFE */
9048 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9049 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9050 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
9051/* Connect Line-in jack to Surround */
9052 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9053 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9054 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
9055/* Connect HP out jack to Front */
9056 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9057 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9058 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangccc656c2006-10-17 12:32:26 +02009059
9060 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yangccc656c2006-10-17 12:32:26 +02009061
9062 { } /* end */
9063};
9064
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009065static struct hda_verb alc883_lenovo_101e_verbs[] = {
9066 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9067 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
9068 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
9069 { } /* end */
9070};
9071
Kailang Yang272a5272007-05-14 11:00:38 +02009072static struct hda_verb alc883_lenovo_nb0763_verbs[] = {
9073 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9074 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9075 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9076 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9077 { } /* end */
9078};
9079
9080static struct hda_verb alc888_lenovo_ms7195_verbs[] = {
9081 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9082 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9083 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9084 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},
9085 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9086 { } /* end */
9087};
9088
Kailang Yang189609a2007-08-20 11:31:23 +02009089static struct hda_verb alc883_haier_w66_verbs[] = {
9090 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9091 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9092
9093 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9094
9095 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
9096 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9097 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9098 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9099 { } /* end */
9100};
9101
Kailang Yange2757d52008-08-26 13:17:46 +02009102static struct hda_verb alc888_lenovo_sky_verbs[] = {
9103 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9104 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9105 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9106 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9107 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9108 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9109 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
9110 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9111 { } /* end */
9112};
9113
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03009114static struct hda_verb alc888_6st_dell_verbs[] = {
9115 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9116 { }
9117};
9118
Guido Günther3e1647c2009-06-05 00:47:26 +02009119static struct hda_verb alc883_vaiott_verbs[] = {
9120 /* HP */
9121 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9122 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9123
9124 /* enable unsolicited event */
9125 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9126
9127 { } /* end */
9128};
9129
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009130static void alc888_3st_hp_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03009131{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009132 struct alc_spec *spec = codec->spec;
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03009133
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009134 spec->autocfg.hp_pins[0] = 0x1b;
9135 spec->autocfg.speaker_pins[0] = 0x14;
9136 spec->autocfg.speaker_pins[1] = 0x16;
9137 spec->autocfg.speaker_pins[2] = 0x18;
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03009138}
9139
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009140static struct hda_verb alc888_3st_hp_verbs[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009141 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
Herton Ronaldo Krzesinskif32a19e2008-03-18 09:27:08 +01009142 {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
9143 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009144 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Herton Ronaldo Krzesinski8718b702009-03-04 14:22:51 -03009145 { } /* end */
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009146};
9147
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03009148/*
9149 * 2ch mode
9150 */
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009151static struct hda_verb alc888_3st_hp_2ch_init[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009152 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
9153 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9154 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
9155 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03009156 { } /* end */
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009157};
9158
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03009159/*
9160 * 4ch mode
9161 */
9162static struct hda_verb alc888_3st_hp_4ch_init[] = {
9163 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
9164 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
9165 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9166 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
9167 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
9168 { } /* end */
9169};
9170
9171/*
9172 * 6ch mode
9173 */
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009174static struct hda_verb alc888_3st_hp_6ch_init[] = {
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009175 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9176 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03009177 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009178 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
9179 { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03009180 { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
9181 { } /* end */
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009182};
9183
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03009184static struct hda_channel_mode alc888_3st_hp_modes[3] = {
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009185 { 2, alc888_3st_hp_2ch_init },
Herton Ronaldo Krzesinski3ea0d7c2009-03-04 14:22:50 -03009186 { 4, alc888_3st_hp_4ch_init },
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009187 { 6, alc888_3st_hp_6ch_init },
Claudio Matsuoka8341de62007-07-06 12:10:45 +02009188};
9189
Kailang Yang272a5272007-05-14 11:00:38 +02009190/* toggle front-jack and RCA according to the hp-jack state */
9191static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
9192{
Wu Fengguang864f92b2009-11-18 12:38:02 +08009193 unsigned int present = snd_hda_jack_detect(codec, 0x1b);
Kailang Yangea1fb292008-08-26 12:58:38 +02009194
Takashi Iwai47fd8302007-08-10 17:11:07 +02009195 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9196 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9197 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9198 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
Kailang Yang272a5272007-05-14 11:00:38 +02009199}
9200
9201/* toggle RCA according to the front-jack state */
9202static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
9203{
Wu Fengguang864f92b2009-11-18 12:38:02 +08009204 unsigned int present = snd_hda_jack_detect(codec, 0x14);
Kailang Yangea1fb292008-08-26 12:58:38 +02009205
Takashi Iwai47fd8302007-08-10 17:11:07 +02009206 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9207 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
Kailang Yang272a5272007-05-14 11:00:38 +02009208}
Takashi Iwai47fd8302007-08-10 17:11:07 +02009209
Kailang Yang272a5272007-05-14 11:00:38 +02009210static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
9211 unsigned int res)
9212{
9213 if ((res >> 26) == ALC880_HP_EVENT)
9214 alc888_lenovo_ms7195_front_automute(codec);
9215 if ((res >> 26) == ALC880_FRONT_EVENT)
9216 alc888_lenovo_ms7195_rca_automute(codec);
9217}
9218
9219static struct hda_verb alc883_medion_md2_verbs[] = {
9220 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9221 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9222
9223 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9224
9225 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9226 { } /* end */
9227};
9228
9229/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009230static void alc883_medion_md2_setup(struct hda_codec *codec)
Kailang Yang272a5272007-05-14 11:00:38 +02009231{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009232 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02009233
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009234 spec->autocfg.hp_pins[0] = 0x14;
9235 spec->autocfg.speaker_pins[0] = 0x15;
Kailang Yang272a5272007-05-14 11:00:38 +02009236}
9237
Kailang Yangccc656c2006-10-17 12:32:26 +02009238/* toggle speaker-output according to the hp-jack state */
Sasha Alexandrc2592492009-06-16 14:52:54 -04009239#define alc883_targa_init_hook alc882_targa_init_hook
9240#define alc883_targa_unsol_event alc882_targa_unsol_event
Jiang zhe368c7a92008-03-04 11:20:33 +01009241
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009242static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
9243{
9244 unsigned int present;
9245
Takashi Iwaid56757a2009-11-18 08:00:14 +01009246 present = snd_hda_jack_detect(codec, 0x18);
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009247 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
9248 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9249}
9250
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009251static void alc883_clevo_m720_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009252{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009253 struct alc_spec *spec = codec->spec;
9254
9255 spec->autocfg.hp_pins[0] = 0x15;
9256 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009257}
9258
9259static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
9260{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009261 alc_automute_amp(codec);
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009262 alc883_clevo_m720_mic_automute(codec);
9263}
9264
9265static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
Jiang zhe368c7a92008-03-04 11:20:33 +01009266 unsigned int res)
9267{
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009268 switch (res >> 26) {
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009269 case ALC880_MIC_EVENT:
9270 alc883_clevo_m720_mic_automute(codec);
9271 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009272 default:
9273 alc_automute_amp_unsol_event(codec, res);
9274 break;
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009275 }
Jiang zhe368c7a92008-03-04 11:20:33 +01009276}
9277
Jiang zhefb97dc62008-03-06 11:07:11 +01009278/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009279static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
Jiang zhefb97dc62008-03-06 11:07:11 +01009280{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009281 struct alc_spec *spec = codec->spec;
Jiang zhefb97dc62008-03-06 11:07:11 +01009282
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009283 spec->autocfg.hp_pins[0] = 0x14;
9284 spec->autocfg.speaker_pins[0] = 0x15;
Jiang zhefb97dc62008-03-06 11:07:11 +01009285}
9286
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009287static void alc883_haier_w66_setup(struct hda_codec *codec)
Jiang zhefb97dc62008-03-06 11:07:11 +01009288{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009289 struct alc_spec *spec = codec->spec;
Jiang zhefb97dc62008-03-06 11:07:11 +01009290
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009291 spec->autocfg.hp_pins[0] = 0x1b;
9292 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang189609a2007-08-20 11:31:23 +02009293}
9294
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009295static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
9296{
Wu Fengguang864f92b2009-11-18 12:38:02 +08009297 int bits = snd_hda_jack_detect(codec, 0x14) ? HDA_AMP_MUTE : 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009298
Takashi Iwai47fd8302007-08-10 17:11:07 +02009299 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9300 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009301}
9302
9303static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
9304{
Wu Fengguang864f92b2009-11-18 12:38:02 +08009305 int bits = snd_hda_jack_detect(codec, 0x1b) ? HDA_AMP_MUTE : 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009306
Takashi Iwai47fd8302007-08-10 17:11:07 +02009307 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
9308 HDA_AMP_MUTE, bits);
9309 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9310 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009311}
9312
9313static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
9314 unsigned int res)
9315{
9316 if ((res >> 26) == ALC880_HP_EVENT)
9317 alc883_lenovo_101e_all_automute(codec);
9318 if ((res >> 26) == ALC880_FRONT_EVENT)
9319 alc883_lenovo_101e_ispeaker_automute(codec);
9320}
9321
Takashi Iwai676a9b52007-08-16 15:23:35 +02009322/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009323static void alc883_acer_aspire_setup(struct hda_codec *codec)
Takashi Iwai676a9b52007-08-16 15:23:35 +02009324{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009325 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02009326
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009327 spec->autocfg.hp_pins[0] = 0x14;
9328 spec->autocfg.speaker_pins[0] = 0x15;
9329 spec->autocfg.speaker_pins[1] = 0x16;
Takashi Iwai676a9b52007-08-16 15:23:35 +02009330}
9331
Kailang Yangd1a991a2007-08-15 16:21:59 +02009332static struct hda_verb alc883_acer_eapd_verbs[] = {
9333 /* HP Pin: output 0 (0x0c) */
9334 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9335 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9336 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9337 /* Front Pin: output 0 (0x0c) */
Takashi Iwai676a9b52007-08-16 15:23:35 +02009338 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9339 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangd1a991a2007-08-15 16:21:59 +02009340 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Kailang Yangd1a991a2007-08-15 16:21:59 +02009341 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
9342 /* eanable EAPD on medion laptop */
9343 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
9344 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
Takashi Iwai676a9b52007-08-16 15:23:35 +02009345 /* enable unsolicited event */
9346 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Kailang Yangd1a991a2007-08-15 16:21:59 +02009347 { }
9348};
9349
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009350static struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
9351 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9352 {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
9353 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9354 { } /* end */
9355};
9356
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009357static void alc888_6st_dell_setup(struct hda_codec *codec)
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009358{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009359 struct alc_spec *spec = codec->spec;
Kailang Yangea1fb292008-08-26 12:58:38 +02009360
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009361 spec->autocfg.hp_pins[0] = 0x1b;
9362 spec->autocfg.speaker_pins[0] = 0x14;
9363 spec->autocfg.speaker_pins[1] = 0x15;
9364 spec->autocfg.speaker_pins[2] = 0x16;
9365 spec->autocfg.speaker_pins[3] = 0x17;
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009366}
9367
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009368static void alc888_lenovo_sky_setup(struct hda_codec *codec)
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009369{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009370 struct alc_spec *spec = codec->spec;
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009371
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009372 spec->autocfg.hp_pins[0] = 0x1b;
9373 spec->autocfg.speaker_pins[0] = 0x14;
9374 spec->autocfg.speaker_pins[1] = 0x15;
9375 spec->autocfg.speaker_pins[2] = 0x16;
9376 spec->autocfg.speaker_pins[3] = 0x17;
9377 spec->autocfg.speaker_pins[4] = 0x1a;
Kailang Yange2757d52008-08-26 13:17:46 +02009378}
9379
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009380static void alc883_vaiott_setup(struct hda_codec *codec)
Guido Günther3e1647c2009-06-05 00:47:26 +02009381{
9382 struct alc_spec *spec = codec->spec;
9383
9384 spec->autocfg.hp_pins[0] = 0x15;
9385 spec->autocfg.speaker_pins[0] = 0x14;
9386 spec->autocfg.speaker_pins[1] = 0x17;
Guido Günther3e1647c2009-06-05 00:47:26 +02009387}
9388
Kailang Yange2757d52008-08-26 13:17:46 +02009389static struct hda_verb alc888_asus_m90v_verbs[] = {
9390 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9391 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9392 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9393 /* enable unsolicited event */
9394 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9395 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
9396 { } /* end */
9397};
9398
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009399static void alc883_mode2_setup(struct hda_codec *codec)
Kailang Yange2757d52008-08-26 13:17:46 +02009400{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009401 struct alc_spec *spec = codec->spec;
Kailang Yange2757d52008-08-26 13:17:46 +02009402
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009403 spec->autocfg.hp_pins[0] = 0x1b;
9404 spec->autocfg.speaker_pins[0] = 0x14;
9405 spec->autocfg.speaker_pins[1] = 0x15;
9406 spec->autocfg.speaker_pins[2] = 0x16;
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009407 spec->ext_mic.pin = 0x18;
9408 spec->int_mic.pin = 0x19;
9409 spec->ext_mic.mux_idx = 0;
9410 spec->int_mic.mux_idx = 1;
9411 spec->auto_mic = 1;
Kailang Yange2757d52008-08-26 13:17:46 +02009412}
9413
9414static struct hda_verb alc888_asus_eee1601_verbs[] = {
9415 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9416 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9417 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9418 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9419 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9420 {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
9421 {0x20, AC_VERB_SET_PROC_COEF, 0x0838},
9422 /* enable unsolicited event */
9423 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9424 { } /* end */
9425};
9426
Kailang Yange2757d52008-08-26 13:17:46 +02009427static void alc883_eee1601_inithook(struct hda_codec *codec)
9428{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +02009429 struct alc_spec *spec = codec->spec;
9430
9431 spec->autocfg.hp_pins[0] = 0x14;
9432 spec->autocfg.speaker_pins[0] = 0x1b;
9433 alc_automute_pin(codec);
Kailang Yange2757d52008-08-26 13:17:46 +02009434}
9435
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009436static struct hda_verb alc889A_mb31_verbs[] = {
9437 /* Init rear pin (used as headphone output) */
9438 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */
9439 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */
9440 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
9441 /* Init line pin (used as output in 4ch and 6ch mode) */
9442 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */
9443 /* Init line 2 pin (used as headphone out by default) */
9444 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */
9445 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
9446 { } /* end */
9447};
9448
9449/* Mute speakers according to the headphone jack state */
9450static void alc889A_mb31_automute(struct hda_codec *codec)
9451{
9452 unsigned int present;
9453
9454 /* Mute only in 2ch or 4ch mode */
9455 if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
9456 == 0x00) {
Wu Fengguang864f92b2009-11-18 12:38:02 +08009457 present = snd_hda_jack_detect(codec, 0x15);
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009458 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
9459 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9460 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
9461 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
9462 }
9463}
9464
9465static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
9466{
9467 if ((res >> 26) == ALC880_HP_EVENT)
9468 alc889A_mb31_automute(codec);
9469}
9470
Takashi Iwai49535502009-06-30 15:28:30 +02009471
Takashi Iwaicb53c622007-08-10 17:21:45 +02009472#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwai49535502009-06-30 15:28:30 +02009473#define alc882_loopbacks alc880_loopbacks
Takashi Iwaicb53c622007-08-10 17:21:45 +02009474#endif
9475
Sasha Alexandrdef319f2009-06-16 16:00:15 -04009476/* pcm configuration: identical with ALC880 */
Takashi Iwai49535502009-06-30 15:28:30 +02009477#define alc882_pcm_analog_playback alc880_pcm_analog_playback
9478#define alc882_pcm_analog_capture alc880_pcm_analog_capture
9479#define alc882_pcm_digital_playback alc880_pcm_digital_playback
9480#define alc882_pcm_digital_capture alc880_pcm_digital_capture
9481
9482static hda_nid_t alc883_slave_dig_outs[] = {
9483 ALC1200_DIGOUT_NID, 0,
9484};
9485
9486static hda_nid_t alc1200_slave_dig_outs[] = {
9487 ALC883_DIGOUT_NID, 0,
9488};
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009489
9490/*
9491 * configuration and preset
9492 */
Takashi Iwai49535502009-06-30 15:28:30 +02009493static const char *alc882_models[ALC882_MODEL_LAST] = {
9494 [ALC882_3ST_DIG] = "3stack-dig",
9495 [ALC882_6ST_DIG] = "6stack-dig",
9496 [ALC882_ARIMA] = "arima",
9497 [ALC882_W2JC] = "w2jc",
9498 [ALC882_TARGA] = "targa",
9499 [ALC882_ASUS_A7J] = "asus-a7j",
9500 [ALC882_ASUS_A7M] = "asus-a7m",
9501 [ALC885_MACPRO] = "macpro",
9502 [ALC885_MB5] = "mb5",
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009503 [ALC885_MACMINI3] = "macmini3",
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08009504 [ALC885_MBA21] = "mba21",
Takashi Iwai49535502009-06-30 15:28:30 +02009505 [ALC885_MBP3] = "mbp3",
9506 [ALC885_IMAC24] = "imac24",
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009507 [ALC885_IMAC91] = "imac91",
Takashi Iwai49535502009-06-30 15:28:30 +02009508 [ALC883_3ST_2ch_DIG] = "3stack-2ch-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009509 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
9510 [ALC883_3ST_6ch] = "3stack-6ch",
Takashi Iwai49535502009-06-30 15:28:30 +02009511 [ALC883_6ST_DIG] = "alc883-6stack-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009512 [ALC883_TARGA_DIG] = "targa-dig",
9513 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
David Heidelberger64a8be72009-06-08 16:15:18 +02009514 [ALC883_TARGA_8ch_DIG] = "targa-8ch-dig",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009515 [ALC883_ACER] = "acer",
Tobin Davis2880a862007-08-07 11:50:26 +02009516 [ALC883_ACER_ASPIRE] = "acer-aspire",
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009517 [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g",
Takashi Iwaib1a91462009-06-21 10:56:44 +02009518 [ALC888_ACER_ASPIRE_6530G] = "acer-aspire-6530g",
Hector Martin3b315d72009-06-02 10:54:19 +02009519 [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g",
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009520 [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009521 [ALC883_MEDION] = "medion",
Kailang Yang272a5272007-05-14 11:00:38 +02009522 [ALC883_MEDION_MD2] = "medion-md2",
Maurus Cuelenaere7ad7b212010-04-06 18:12:52 +02009523 [ALC883_MEDION_WIM2160] = "medion-wim2160",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009524 [ALC883_LAPTOP_EAPD] = "laptop-eapd",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02009525 [ALC883_LENOVO_101E_2ch] = "lenovo-101e",
Kailang Yang272a5272007-05-14 11:00:38 +02009526 [ALC883_LENOVO_NB0763] = "lenovo-nb0763",
9527 [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
Kailang Yange2757d52008-08-26 13:17:46 +02009528 [ALC888_LENOVO_SKY] = "lenovo-sky",
Kailang Yang189609a2007-08-20 11:31:23 +02009529 [ALC883_HAIER_W66] = "haier-w66",
Claudio Matsuoka4723c022007-07-13 14:36:19 +02009530 [ALC888_3ST_HP] = "3stack-hp",
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009531 [ALC888_6ST_DELL] = "6stack-dell",
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +01009532 [ALC883_MITAC] = "mitac",
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04309533 [ALC883_CLEVO_M540R] = "clevo-m540r",
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009534 [ALC883_CLEVO_M720] = "clevo-m720",
Jiang zhefb97dc62008-03-06 11:07:11 +01009535 [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009536 [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
Jiang zhe17bba1b2008-06-04 12:11:07 +02009537 [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009538 [ALC889A_INTEL] = "intel-alc889a",
9539 [ALC889_INTEL] = "intel-x58",
Wu Fengguang3ab90932008-11-17 09:51:09 +01009540 [ALC1200_ASUS_P5Q] = "asus-p5q",
Torben Schulzeb4c41d2009-05-18 15:02:35 +02009541 [ALC889A_MB31] = "mb31",
Guido Günther3e1647c2009-06-05 00:47:26 +02009542 [ALC883_SONY_VAIO_TT] = "sony-vaio-tt",
Takashi Iwai49535502009-06-30 15:28:30 +02009543 [ALC882_AUTO] = "auto",
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009544};
9545
Takashi Iwai49535502009-06-30 15:28:30 +02009546static struct snd_pci_quirk alc882_cfg_tbl[] = {
9547 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
9548
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009549 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
Takashi Iwai69e50282008-11-03 10:07:43 +01009550 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
Takashi Iwai9b6682f2009-03-23 22:50:52 +01009551 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009552 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
9553 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
Jaroslav Kysela0b18cb12008-07-28 17:07:07 +02009554 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
Vincent Petry5b2d1ec2008-11-18 22:21:57 +08009555 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
9556 ALC888_ACER_ASPIRE_4930G),
Lukasz Wojnilowicza8e4f9d2009-01-08 12:00:49 +01009557 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
Takashi Iwai83dd7402009-11-24 08:57:53 +01009558 ALC888_ACER_ASPIRE_4930G),
Hector Martin3b315d72009-06-02 10:54:19 +02009559 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
9560 ALC888_ACER_ASPIRE_8930G),
Takashi Iwaie46b0c82009-06-13 10:16:43 +02009561 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
9562 ALC888_ACER_ASPIRE_8930G),
Takashi Iwai49535502009-06-30 15:28:30 +02009563 SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
9564 SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
Lukasz Wojnilowicza8e4f9d2009-01-08 12:00:49 +01009565 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
Takashi Iwaidde65352009-06-25 08:25:35 +02009566 ALC888_ACER_ASPIRE_6530G),
Juan Jesus Garcia de Soriacc374c42009-02-23 08:11:59 +01009567 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
Tony Vroond2fd4b02009-06-21 00:40:10 +01009568 ALC888_ACER_ASPIRE_6530G),
Denis Kuplyakovfc86f952009-08-25 18:15:59 +02009569 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
9570 ALC888_ACER_ASPIRE_7730G),
Takashi Iwai22b530e2009-05-13 11:32:52 +02009571 /* default Acer -- disabled as it causes more problems.
9572 * model=auto should work fine now
9573 */
9574 /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
Takashi Iwai49535502009-06-30 15:28:30 +02009575
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +01009576 SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
Takashi Iwai49535502009-06-30 15:28:30 +02009577
Tobin Davisfebe3372007-06-12 11:27:46 +02009578 SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009579 SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
9580 SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
Herton Ronaldo Krzesinski5d85f8d2008-03-20 12:13:46 +01009581 SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
Chris Bagwell06bf3e12009-01-01 10:32:08 +01009582 SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
Herton Ronaldo Krzesinski7ec30f02009-03-04 14:22:52 -03009583 SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
Takashi Iwai49535502009-06-30 15:28:30 +02009584
9585 SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
9586 SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
9587 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
Kailang Yanga01c30c2008-10-15 11:14:58 +02009588 SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
Takashi Iwai49535502009-06-30 15:28:30 +02009589 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
9590 SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
9591 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009592 SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
Mackenzie Morgan44a678d2009-02-10 17:13:43 +01009593 SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
Wu Fengguang3ab90932008-11-17 09:51:09 +01009594 SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
Kailang Yange2757d52008-08-26 13:17:46 +02009595 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
Takashi Iwai49535502009-06-30 15:28:30 +02009596
9597 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
Travis Place97ec7102008-05-23 18:31:46 +02009598 SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
Takashi Iwai49535502009-06-30 15:28:30 +02009599 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
Luke Yelavich2de686d2009-01-16 15:08:02 +11009600 SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009601 SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
9602 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
Kailang Yange2757d52008-08-26 13:17:46 +02009603 SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009604 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
Takashi Iwai49535502009-06-30 15:28:30 +02009605 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
9606
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009607 SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
9608 SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
9609 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
Takashi Iwai49535502009-06-30 15:28:30 +02009610 SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
Takashi Iwai2fef62c2009-12-18 08:48:42 +01009611 SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
Takashi Iwai49535502009-06-30 15:28:30 +02009612 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009613 SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
Pascal Terjan82808232008-03-04 11:33:28 +01009614 SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009615 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
9616 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
9617 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
9618 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
9619 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
9620 SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
William Westonb1e44222009-07-08 01:10:05 -07009621 SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009622 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
9623 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
9624 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
Anisse Astierb43f6e52010-03-10 19:17:46 +01009625 SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
David Heidelberger64a8be72009-06-08 16:15:18 +02009626 SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009627 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
9628 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
Tobin Davis799f88a2007-05-29 14:29:08 +02009629 SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
Takashi Iwaiee095432008-11-25 15:03:38 +01009630 SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
Herton Ronaldo Krzesinski86d34b72008-03-18 09:27:59 +01009631 SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
Leonard Norrgard2a296cb2007-01-08 11:28:22 +01009632 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
Tobin Davis2dcd5222007-07-10 17:04:57 +02009633 SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
Sasha Alexandrdf01b8a2009-06-16 14:46:17 -04009634 SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
Anisse Astierb43f6e52010-03-10 19:17:46 +01009635 SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009636 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
William Westonb1e44222009-07-08 01:10:05 -07009637 SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
Takashi Iwai49535502009-06-30 15:28:30 +02009638
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009639 SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
Joerg Schirottked1501ea2010-04-15 08:37:41 +02009640 SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG),
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +01009641 SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
9642 SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -04309643 SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
Takashi Iwaidea0a502009-02-09 17:14:52 +01009644 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
Daniel T Chene60623b2007-05-29 03:41:55 -04009645 SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
Takashi Iwai49535502009-06-30 15:28:30 +02009646 /* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
Takashi Iwaif5fcc132006-11-24 17:07:44 +01009647 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
Takashi Iwaibfb53032009-04-14 14:51:04 +02009648 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
Takashi Iwaif67d8172009-02-04 23:30:19 +01009649 ALC883_FUJITSU_PI2515),
Takashi Iwaibfb53032009-04-14 14:51:04 +02009650 SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
Vincent Petryef8ef5f2008-11-23 11:31:41 +08009651 ALC888_FUJITSU_XA3530),
Kailang Yang272a5272007-05-14 11:00:38 +02009652 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
Kailang Yang272a5272007-05-14 11:00:38 +02009653 SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
Takashi Iwaiac3e3742007-12-17 17:14:18 +01009654 SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
9655 SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
Kailang Yange2757d52008-08-26 13:17:46 +02009656 SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
Kailang Yang272a5272007-05-14 11:00:38 +02009657 SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
Takashi Iwai959973b2008-11-05 11:30:56 +01009658 SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
Andrew Paprocki0b167bf2008-02-03 10:15:44 +01009659 SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
Kailang Yang189609a2007-08-20 11:31:23 +02009660 SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
Takashi Iwai49535502009-06-30 15:28:30 +02009661
Jiang zhe17bba1b2008-06-04 12:11:07 +02009662 SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
9663 SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
Luke Yelavich2de686d2009-01-16 15:08:02 +11009664 SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009665 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
9666 SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
9667 SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
Daniel T Chen572c0e32010-03-14 23:44:03 -04009668 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
Takashi Iwai49535502009-06-30 15:28:30 +02009669
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009670 {}
9671};
9672
Takashi Iwai49535502009-06-30 15:28:30 +02009673/* codec SSID table for Intel Mac */
9674static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
9675 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
9676 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
9677 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
9678 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
9679 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
9680 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
9681 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
Daniel T Chen26fd74f2010-05-30 09:55:23 -04009682 SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
Justin P. Mattockab669962010-06-06 16:09:53 -07009683 SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M),
Justin P. Mattockf53dae22010-06-06 16:09:51 -07009684 SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
Justin P. Mattock6e129702010-06-06 16:09:49 -07009685 SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
Takashi Iwai49535502009-06-30 15:28:30 +02009686 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
9687 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
9688 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009689 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
Takashi Iwai49535502009-06-30 15:28:30 +02009690 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
Luke Yelavich3bfea982010-06-22 11:04:19 +10009691 SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
Daniel T Chen46ef6ec2009-11-11 14:32:10 -05009692 /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
9693 * so apparently no perfect solution yet
Takashi Iwai49535502009-06-30 15:28:30 +02009694 */
9695 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
Daniel T Chen46ef6ec2009-11-11 14:32:10 -05009696 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009697 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
Takashi Iwai49535502009-06-30 15:28:30 +02009698 {} /* terminator */
Wu Fengguangf3cd3f52009-04-02 19:44:18 +08009699};
9700
Takashi Iwai49535502009-06-30 15:28:30 +02009701static struct alc_config_preset alc882_presets[] = {
9702 [ALC882_3ST_DIG] = {
9703 .mixers = { alc882_base_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009704 .init_verbs = { alc882_base_init_verbs,
9705 alc882_adc1_init_verbs },
Takashi Iwai49535502009-06-30 15:28:30 +02009706 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9707 .dac_nids = alc882_dac_nids,
9708 .dig_out_nid = ALC882_DIGOUT_NID,
9709 .dig_in_nid = ALC882_DIGIN_NID,
9710 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9711 .channel_mode = alc882_ch_modes,
9712 .need_dac_fix = 1,
9713 .input_mux = &alc882_capture_source,
9714 },
9715 [ALC882_6ST_DIG] = {
9716 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009717 .init_verbs = { alc882_base_init_verbs,
9718 alc882_adc1_init_verbs },
Takashi Iwai49535502009-06-30 15:28:30 +02009719 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9720 .dac_nids = alc882_dac_nids,
9721 .dig_out_nid = ALC882_DIGOUT_NID,
9722 .dig_in_nid = ALC882_DIGIN_NID,
9723 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
9724 .channel_mode = alc882_sixstack_modes,
9725 .input_mux = &alc882_capture_source,
9726 },
9727 [ALC882_ARIMA] = {
9728 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009729 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9730 alc882_eapd_verbs },
Takashi Iwai49535502009-06-30 15:28:30 +02009731 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9732 .dac_nids = alc882_dac_nids,
9733 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
9734 .channel_mode = alc882_sixstack_modes,
9735 .input_mux = &alc882_capture_source,
9736 },
9737 [ALC882_W2JC] = {
9738 .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009739 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9740 alc882_eapd_verbs, alc880_gpio1_init_verbs },
Takashi Iwai49535502009-06-30 15:28:30 +02009741 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9742 .dac_nids = alc882_dac_nids,
9743 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
9744 .channel_mode = alc880_threestack_modes,
9745 .need_dac_fix = 1,
9746 .input_mux = &alc882_capture_source,
9747 .dig_out_nid = ALC882_DIGOUT_NID,
9748 },
Reimundo Heluani76e6f5a2010-02-23 01:19:51 -08009749 [ALC885_MBA21] = {
9750 .mixers = { alc885_mba21_mixer },
9751 .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
9752 .num_dacs = 2,
9753 .dac_nids = alc882_dac_nids,
9754 .channel_mode = alc885_mba21_ch_modes,
9755 .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
9756 .input_mux = &alc882_capture_source,
9757 .unsol_event = alc_automute_amp_unsol_event,
9758 .setup = alc885_mba21_setup,
9759 .init_hook = alc_automute_amp,
9760 },
Takashi Iwai49535502009-06-30 15:28:30 +02009761 [ALC885_MBP3] = {
9762 .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
9763 .init_verbs = { alc885_mbp3_init_verbs,
9764 alc880_gpio1_init_verbs },
Takashi Iwaibe0ae922009-08-31 08:27:10 +02009765 .num_dacs = 2,
Takashi Iwai49535502009-06-30 15:28:30 +02009766 .dac_nids = alc882_dac_nids,
Takashi Iwaibe0ae922009-08-31 08:27:10 +02009767 .hp_nid = 0x04,
9768 .channel_mode = alc885_mbp_4ch_modes,
9769 .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
Takashi Iwai49535502009-06-30 15:28:30 +02009770 .input_mux = &alc882_capture_source,
9771 .dig_out_nid = ALC882_DIGOUT_NID,
9772 .dig_in_nid = ALC882_DIGIN_NID,
9773 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009774 .setup = alc885_mbp3_setup,
9775 .init_hook = alc_automute_amp,
Takashi Iwai49535502009-06-30 15:28:30 +02009776 },
9777 [ALC885_MB5] = {
9778 .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
9779 .init_verbs = { alc885_mb5_init_verbs,
9780 alc880_gpio1_init_verbs },
9781 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9782 .dac_nids = alc882_dac_nids,
9783 .channel_mode = alc885_mb5_6ch_modes,
9784 .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
9785 .input_mux = &mb5_capture_source,
9786 .dig_out_nid = ALC882_DIGOUT_NID,
9787 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009788 .unsol_event = alc_automute_amp_unsol_event,
9789 .setup = alc885_mb5_setup,
9790 .init_hook = alc_automute_amp,
Takashi Iwai49535502009-06-30 15:28:30 +02009791 },
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009792 [ALC885_MACMINI3] = {
9793 .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
9794 .init_verbs = { alc885_macmini3_init_verbs,
9795 alc880_gpio1_init_verbs },
9796 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9797 .dac_nids = alc882_dac_nids,
9798 .channel_mode = alc885_macmini3_6ch_modes,
9799 .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
9800 .input_mux = &macmini3_capture_source,
9801 .dig_out_nid = ALC882_DIGOUT_NID,
9802 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009803 .unsol_event = alc_automute_amp_unsol_event,
9804 .setup = alc885_macmini3_setup,
9805 .init_hook = alc_automute_amp,
Luke Yelaviche458b1f2010-02-12 16:28:29 +11009806 },
Takashi Iwai49535502009-06-30 15:28:30 +02009807 [ALC885_MACPRO] = {
9808 .mixers = { alc882_macpro_mixer },
9809 .init_verbs = { alc882_macpro_init_verbs },
9810 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9811 .dac_nids = alc882_dac_nids,
9812 .dig_out_nid = ALC882_DIGOUT_NID,
9813 .dig_in_nid = ALC882_DIGIN_NID,
9814 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9815 .channel_mode = alc882_ch_modes,
9816 .input_mux = &alc882_capture_source,
9817 .init_hook = alc885_macpro_init_hook,
9818 },
9819 [ALC885_IMAC24] = {
9820 .mixers = { alc885_imac24_mixer },
9821 .init_verbs = { alc885_imac24_init_verbs },
9822 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9823 .dac_nids = alc882_dac_nids,
9824 .dig_out_nid = ALC882_DIGOUT_NID,
9825 .dig_in_nid = ALC882_DIGIN_NID,
9826 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
9827 .channel_mode = alc882_ch_modes,
9828 .input_mux = &alc882_capture_source,
9829 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009830 .setup = alc885_imac24_setup,
Takashi Iwai49535502009-06-30 15:28:30 +02009831 .init_hook = alc885_imac24_init_hook,
9832 },
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009833 [ALC885_IMAC91] = {
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07009834 .mixers = {alc885_imac91_mixer},
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009835 .init_verbs = { alc885_imac91_init_verbs,
9836 alc880_gpio1_init_verbs },
9837 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9838 .dac_nids = alc882_dac_nids,
Justin P. Mattockb7cccc52010-05-23 10:55:00 -07009839 .channel_mode = alc885_mba21_ch_modes,
9840 .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
9841 .input_mux = &alc889A_imac91_capture_source,
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009842 .dig_out_nid = ALC882_DIGOUT_NID,
9843 .dig_in_nid = ALC882_DIGIN_NID,
Takashi Iwai9d54f082010-02-22 08:34:40 +01009844 .unsol_event = alc_automute_amp_unsol_event,
9845 .setup = alc885_imac91_setup,
9846 .init_hook = alc_automute_amp,
Justin P. Mattock4b7e1802009-12-07 15:07:46 -08009847 },
Takashi Iwai49535502009-06-30 15:28:30 +02009848 [ALC882_TARGA] = {
9849 .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009850 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
Takashi Iwai31909b82009-07-10 12:33:48 +02009851 alc880_gpio3_init_verbs, alc882_targa_verbs},
Takashi Iwai49535502009-06-30 15:28:30 +02009852 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9853 .dac_nids = alc882_dac_nids,
9854 .dig_out_nid = ALC882_DIGOUT_NID,
9855 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
9856 .adc_nids = alc882_adc_nids,
9857 .capsrc_nids = alc882_capsrc_nids,
9858 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
9859 .channel_mode = alc882_3ST_6ch_modes,
9860 .need_dac_fix = 1,
9861 .input_mux = &alc882_capture_source,
9862 .unsol_event = alc882_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009863 .setup = alc882_targa_setup,
9864 .init_hook = alc882_targa_automute,
Takashi Iwai49535502009-06-30 15:28:30 +02009865 },
9866 [ALC882_ASUS_A7J] = {
9867 .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009868 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9869 alc882_asus_a7j_verbs},
Takashi Iwai49535502009-06-30 15:28:30 +02009870 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9871 .dac_nids = alc882_dac_nids,
9872 .dig_out_nid = ALC882_DIGOUT_NID,
9873 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
9874 .adc_nids = alc882_adc_nids,
9875 .capsrc_nids = alc882_capsrc_nids,
9876 .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
9877 .channel_mode = alc882_3ST_6ch_modes,
9878 .need_dac_fix = 1,
9879 .input_mux = &alc882_capture_source,
9880 },
9881 [ALC882_ASUS_A7M] = {
9882 .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
Takashi Iwai8ab9e0a2009-07-03 10:58:12 +02009883 .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
9884 alc882_eapd_verbs, alc880_gpio1_init_verbs,
Takashi Iwai49535502009-06-30 15:28:30 +02009885 alc882_asus_a7m_verbs },
9886 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
9887 .dac_nids = alc882_dac_nids,
9888 .dig_out_nid = ALC882_DIGOUT_NID,
9889 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
9890 .channel_mode = alc880_threestack_modes,
9891 .need_dac_fix = 1,
9892 .input_mux = &alc882_capture_source,
9893 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009894 [ALC883_3ST_2ch_DIG] = {
9895 .mixers = { alc883_3ST_2ch_mixer },
9896 .init_verbs = { alc883_init_verbs },
9897 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9898 .dac_nids = alc883_dac_nids,
9899 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009900 .dig_in_nid = ALC883_DIGIN_NID,
9901 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
9902 .channel_mode = alc883_3ST_2ch_modes,
9903 .input_mux = &alc883_capture_source,
9904 },
9905 [ALC883_3ST_6ch_DIG] = {
9906 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9907 .init_verbs = { alc883_init_verbs },
9908 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9909 .dac_nids = alc883_dac_nids,
9910 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009911 .dig_in_nid = ALC883_DIGIN_NID,
9912 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9913 .channel_mode = alc883_3ST_6ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02009914 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009915 .input_mux = &alc883_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02009916 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009917 [ALC883_3ST_6ch] = {
9918 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
9919 .init_verbs = { alc883_init_verbs },
9920 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9921 .dac_nids = alc883_dac_nids,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009922 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9923 .channel_mode = alc883_3ST_6ch_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +02009924 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009925 .input_mux = &alc883_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +02009926 },
Jiang zhe17bba1b2008-06-04 12:11:07 +02009927 [ALC883_3ST_6ch_INTEL] = {
9928 .mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
9929 .init_verbs = { alc883_init_verbs },
9930 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9931 .dac_nids = alc883_dac_nids,
9932 .dig_out_nid = ALC883_DIGOUT_NID,
9933 .dig_in_nid = ALC883_DIGIN_NID,
Wu Fengguangf3cd3f52009-04-02 19:44:18 +08009934 .slave_dig_outs = alc883_slave_dig_outs,
Jiang zhe17bba1b2008-06-04 12:11:07 +02009935 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
9936 .channel_mode = alc883_3ST_6ch_intel_modes,
9937 .need_dac_fix = 1,
9938 .input_mux = &alc883_3stack_6ch_intel,
9939 },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009940 [ALC889A_INTEL] = {
9941 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +02009942 .init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
9943 alc_hp15_unsol_verbs },
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009944 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9945 .dac_nids = alc883_dac_nids,
9946 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
9947 .adc_nids = alc889_adc_nids,
9948 .dig_out_nid = ALC883_DIGOUT_NID,
9949 .dig_in_nid = ALC883_DIGIN_NID,
9950 .slave_dig_outs = alc883_slave_dig_outs,
9951 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
9952 .channel_mode = alc889_8ch_intel_modes,
9953 .capsrc_nids = alc889_capsrc_nids,
9954 .input_mux = &alc889_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009955 .setup = alc889_automute_setup,
9956 .init_hook = alc_automute_amp,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009957 .unsol_event = alc_automute_amp_unsol_event,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009958 .need_dac_fix = 1,
9959 },
9960 [ALC889_INTEL] = {
9961 .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
9962 .init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009963 alc889_eapd_verbs, alc_hp15_unsol_verbs},
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009964 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9965 .dac_nids = alc883_dac_nids,
9966 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
9967 .adc_nids = alc889_adc_nids,
9968 .dig_out_nid = ALC883_DIGOUT_NID,
9969 .dig_in_nid = ALC883_DIGIN_NID,
9970 .slave_dig_outs = alc883_slave_dig_outs,
9971 .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
9972 .channel_mode = alc889_8ch_intel_modes,
9973 .capsrc_nids = alc889_capsrc_nids,
9974 .input_mux = &alc889_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +02009975 .setup = alc889_automute_setup,
Wu Fengguang6732bd02009-07-30 09:19:14 +02009976 .init_hook = alc889_intel_init_hook,
9977 .unsol_event = alc_automute_amp_unsol_event,
Jaroslav Kysela87a8c372009-07-23 10:58:29 +02009978 .need_dac_fix = 1,
9979 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009980 [ALC883_6ST_DIG] = {
9981 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
9982 .init_verbs = { alc883_init_verbs },
9983 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9984 .dac_nids = alc883_dac_nids,
9985 .dig_out_nid = ALC883_DIGOUT_NID,
Takashi Iwai9c7f8522006-06-28 15:08:22 +02009986 .dig_in_nid = ALC883_DIGIN_NID,
9987 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
9988 .channel_mode = alc883_sixstack_modes,
9989 .input_mux = &alc883_capture_source,
9990 },
Kailang Yangccc656c2006-10-17 12:32:26 +02009991 [ALC883_TARGA_DIG] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -04009992 .mixers = { alc883_targa_mixer, alc883_chmode_mixer },
David Heidelberger005b1072009-07-09 18:45:46 +02009993 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
9994 alc883_targa_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +02009995 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
9996 .dac_nids = alc883_dac_nids,
9997 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yangccc656c2006-10-17 12:32:26 +02009998 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
9999 .channel_mode = alc883_3ST_6ch_modes,
10000 .need_dac_fix = 1,
10001 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -040010002 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010003 .setup = alc882_targa_setup,
10004 .init_hook = alc882_targa_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +020010005 },
10006 [ALC883_TARGA_2ch_DIG] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -040010007 .mixers = { alc883_targa_2ch_mixer},
David Heidelberger005b1072009-07-09 18:45:46 +020010008 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
10009 alc883_targa_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +020010010 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10011 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +010010012 .adc_nids = alc883_adc_nids_alt,
10013 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +010010014 .capsrc_nids = alc883_capsrc_nids,
Kailang Yangccc656c2006-10-17 12:32:26 +020010015 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yangccc656c2006-10-17 12:32:26 +020010016 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10017 .channel_mode = alc883_3ST_2ch_modes,
10018 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -040010019 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010020 .setup = alc882_targa_setup,
10021 .init_hook = alc882_targa_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +020010022 },
David Heidelberger64a8be72009-06-08 16:15:18 +020010023 [ALC883_TARGA_8ch_DIG] = {
Takashi Iwaib99dba32009-09-17 18:23:00 +020010024 .mixers = { alc883_targa_mixer, alc883_targa_8ch_mixer,
10025 alc883_chmode_mixer },
David Heidelberger64a8be72009-06-08 16:15:18 +020010026 .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
Sasha Alexandrc2592492009-06-16 14:52:54 -040010027 alc883_targa_verbs },
David Heidelberger64a8be72009-06-08 16:15:18 +020010028 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10029 .dac_nids = alc883_dac_nids,
10030 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10031 .adc_nids = alc883_adc_nids_rev,
10032 .capsrc_nids = alc883_capsrc_nids_rev,
10033 .dig_out_nid = ALC883_DIGOUT_NID,
10034 .dig_in_nid = ALC883_DIGIN_NID,
10035 .num_channel_mode = ARRAY_SIZE(alc883_4ST_8ch_modes),
10036 .channel_mode = alc883_4ST_8ch_modes,
10037 .need_dac_fix = 1,
10038 .input_mux = &alc883_capture_source,
Sasha Alexandrc2592492009-06-16 14:52:54 -040010039 .unsol_event = alc883_targa_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010040 .setup = alc882_targa_setup,
10041 .init_hook = alc882_targa_automute,
David Heidelberger64a8be72009-06-08 16:15:18 +020010042 },
Vladimir Avdoninbab282b2006-08-22 13:31:58 +020010043 [ALC883_ACER] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +020010044 .mixers = { alc883_base_mixer },
Vladimir Avdoninbab282b2006-08-22 13:31:58 +020010045 /* On TravelMate laptops, GPIO 0 enables the internal speaker
10046 * and the headphone jack. Turn this on and rely on the
10047 * standard mute methods whenever the user wants to turn
10048 * these outputs off.
10049 */
10050 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
10051 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10052 .dac_nids = alc883_dac_nids,
Vladimir Avdoninbab282b2006-08-22 13:31:58 +020010053 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10054 .channel_mode = alc883_3ST_2ch_modes,
10055 .input_mux = &alc883_capture_source,
10056 },
Tobin Davis2880a862007-08-07 11:50:26 +020010057 [ALC883_ACER_ASPIRE] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +020010058 .mixers = { alc883_acer_aspire_mixer },
Kailang Yangd1a991a2007-08-15 16:21:59 +020010059 .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
Tobin Davis2880a862007-08-07 11:50:26 +020010060 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10061 .dac_nids = alc883_dac_nids,
10062 .dig_out_nid = ALC883_DIGOUT_NID,
Tobin Davis2880a862007-08-07 11:50:26 +020010063 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10064 .channel_mode = alc883_3ST_2ch_modes,
10065 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010066 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010067 .setup = alc883_acer_aspire_setup,
10068 .init_hook = alc_automute_amp,
Kailang Yangd1a991a2007-08-15 16:21:59 +020010069 },
Vincent Petry5b2d1ec2008-11-18 22:21:57 +080010070 [ALC888_ACER_ASPIRE_4930G] = {
Vincent Petryef8ef5f2008-11-23 11:31:41 +080010071 .mixers = { alc888_base_mixer,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +080010072 alc883_chmode_mixer },
10073 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10074 alc888_acer_aspire_4930g_verbs },
10075 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10076 .dac_nids = alc883_dac_nids,
10077 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10078 .adc_nids = alc883_adc_nids_rev,
10079 .capsrc_nids = alc883_capsrc_nids_rev,
10080 .dig_out_nid = ALC883_DIGOUT_NID,
10081 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10082 .channel_mode = alc883_3ST_6ch_modes,
10083 .need_dac_fix = 1,
Łukasz Wojniłowicz973b8cb2010-01-24 14:12:37 +010010084 .const_channel_count = 6,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +080010085 .num_mux_defs =
Vincent Petryef8ef5f2008-11-23 11:31:41 +080010086 ARRAY_SIZE(alc888_2_capture_sources),
10087 .input_mux = alc888_2_capture_sources,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010088 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010089 .setup = alc888_acer_aspire_4930g_setup,
10090 .init_hook = alc_automute_amp,
Vincent Petry5b2d1ec2008-11-18 22:21:57 +080010091 },
Tony Vroond2fd4b02009-06-21 00:40:10 +010010092 [ALC888_ACER_ASPIRE_6530G] = {
10093 .mixers = { alc888_acer_aspire_6530_mixer },
10094 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10095 alc888_acer_aspire_6530g_verbs },
10096 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10097 .dac_nids = alc883_dac_nids,
10098 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10099 .adc_nids = alc883_adc_nids_rev,
10100 .capsrc_nids = alc883_capsrc_nids_rev,
10101 .dig_out_nid = ALC883_DIGOUT_NID,
10102 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10103 .channel_mode = alc883_3ST_2ch_modes,
10104 .num_mux_defs =
10105 ARRAY_SIZE(alc888_2_capture_sources),
10106 .input_mux = alc888_acer_aspire_6530_sources,
10107 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010108 .setup = alc888_acer_aspire_6530g_setup,
10109 .init_hook = alc_automute_amp,
Tony Vroond2fd4b02009-06-21 00:40:10 +010010110 },
Hector Martin3b315d72009-06-02 10:54:19 +020010111 [ALC888_ACER_ASPIRE_8930G] = {
Hector Martin556eea92009-12-20 22:51:23 +010010112 .mixers = { alc889_acer_aspire_8930g_mixer,
Hector Martin3b315d72009-06-02 10:54:19 +020010113 alc883_chmode_mixer },
10114 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
Hector Martin0f86a222009-12-20 22:51:18 +010010115 alc889_acer_aspire_8930g_verbs,
10116 alc889_eapd_verbs},
Hector Martin3b315d72009-06-02 10:54:19 +020010117 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10118 .dac_nids = alc883_dac_nids,
Hector Martin018df412009-06-04 00:13:40 +020010119 .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
10120 .adc_nids = alc889_adc_nids,
10121 .capsrc_nids = alc889_capsrc_nids,
Hector Martin3b315d72009-06-02 10:54:19 +020010122 .dig_out_nid = ALC883_DIGOUT_NID,
10123 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10124 .channel_mode = alc883_3ST_6ch_modes,
10125 .need_dac_fix = 1,
10126 .const_channel_count = 6,
10127 .num_mux_defs =
Hector Martin018df412009-06-04 00:13:40 +020010128 ARRAY_SIZE(alc889_capture_sources),
10129 .input_mux = alc889_capture_sources,
Hector Martin3b315d72009-06-02 10:54:19 +020010130 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010131 .setup = alc889_acer_aspire_8930g_setup,
10132 .init_hook = alc_automute_amp,
Hector Martinf5de24b2009-12-20 22:51:31 +010010133#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -050010134 .power_hook = alc_power_eapd,
Hector Martinf5de24b2009-12-20 22:51:31 +010010135#endif
Hector Martin3b315d72009-06-02 10:54:19 +020010136 },
Denis Kuplyakovfc86f952009-08-25 18:15:59 +020010137 [ALC888_ACER_ASPIRE_7730G] = {
10138 .mixers = { alc883_3ST_6ch_mixer,
10139 alc883_chmode_mixer },
10140 .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
10141 alc888_acer_aspire_7730G_verbs },
10142 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10143 .dac_nids = alc883_dac_nids,
10144 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10145 .adc_nids = alc883_adc_nids_rev,
10146 .capsrc_nids = alc883_capsrc_nids_rev,
10147 .dig_out_nid = ALC883_DIGOUT_NID,
10148 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10149 .channel_mode = alc883_3ST_6ch_modes,
10150 .need_dac_fix = 1,
10151 .const_channel_count = 6,
10152 .input_mux = &alc883_capture_source,
10153 .unsol_event = alc_automute_amp_unsol_event,
10154 .setup = alc888_acer_aspire_6530g_setup,
10155 .init_hook = alc_automute_amp,
10156 },
Tobin Davisc07584c2006-10-13 12:32:16 +020010157 [ALC883_MEDION] = {
10158 .mixers = { alc883_fivestack_mixer,
10159 alc883_chmode_mixer },
10160 .init_verbs = { alc883_init_verbs,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +010010161 alc883_medion_eapd_verbs },
Tobin Davisc07584c2006-10-13 12:32:16 +020010162 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10163 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +010010164 .adc_nids = alc883_adc_nids_alt,
10165 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +010010166 .capsrc_nids = alc883_capsrc_nids,
Tobin Davisc07584c2006-10-13 12:32:16 +020010167 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10168 .channel_mode = alc883_sixstack_modes,
10169 .input_mux = &alc883_capture_source,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +010010170 },
Kailang Yang272a5272007-05-14 11:00:38 +020010171 [ALC883_MEDION_MD2] = {
10172 .mixers = { alc883_medion_md2_mixer},
10173 .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs},
10174 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10175 .dac_nids = alc883_dac_nids,
10176 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang272a5272007-05-14 11:00:38 +020010177 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10178 .channel_mode = alc883_3ST_2ch_modes,
10179 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010180 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010181 .setup = alc883_medion_md2_setup,
10182 .init_hook = alc_automute_amp,
Kailang Yangea1fb292008-08-26 12:58:38 +020010183 },
Maurus Cuelenaere7ad7b212010-04-06 18:12:52 +020010184 [ALC883_MEDION_WIM2160] = {
10185 .mixers = { alc883_medion_wim2160_mixer },
10186 .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs },
10187 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10188 .dac_nids = alc883_dac_nids,
10189 .dig_out_nid = ALC883_DIGOUT_NID,
10190 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
10191 .adc_nids = alc883_adc_nids,
10192 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10193 .channel_mode = alc883_3ST_2ch_modes,
10194 .input_mux = &alc883_capture_source,
10195 .unsol_event = alc_automute_amp_unsol_event,
10196 .setup = alc883_medion_wim2160_setup,
10197 .init_hook = alc_automute_amp,
10198 },
Andrew L. Neporadab373bde2006-11-07 11:37:08 +010010199 [ALC883_LAPTOP_EAPD] = {
Takashi Iwai676a9b52007-08-16 15:23:35 +020010200 .mixers = { alc883_base_mixer },
Andrew L. Neporadab373bde2006-11-07 11:37:08 +010010201 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
10202 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10203 .dac_nids = alc883_dac_nids,
Andrew L. Neporadab373bde2006-11-07 11:37:08 +010010204 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10205 .channel_mode = alc883_3ST_2ch_modes,
10206 .input_mux = &alc883_capture_source,
10207 },
ddiaz@cenditel.gob.vea65cc602009-09-05 16:28:06 -043010208 [ALC883_CLEVO_M540R] = {
10209 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10210 .init_verbs = { alc883_init_verbs, alc883_clevo_m540r_verbs },
10211 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10212 .dac_nids = alc883_dac_nids,
10213 .dig_out_nid = ALC883_DIGOUT_NID,
10214 .dig_in_nid = ALC883_DIGIN_NID,
10215 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_clevo_modes),
10216 .channel_mode = alc883_3ST_6ch_clevo_modes,
10217 .need_dac_fix = 1,
10218 .input_mux = &alc883_capture_source,
10219 /* This machine has the hardware HP auto-muting, thus
10220 * we need no software mute via unsol event
10221 */
10222 },
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +010010223 [ALC883_CLEVO_M720] = {
10224 .mixers = { alc883_clevo_m720_mixer },
10225 .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
Jiang zhe368c7a92008-03-04 11:20:33 +010010226 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10227 .dac_nids = alc883_dac_nids,
10228 .dig_out_nid = ALC883_DIGOUT_NID,
10229 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10230 .channel_mode = alc883_3ST_2ch_modes,
10231 .input_mux = &alc883_capture_source,
Herton Ronaldo Krzesinski0c4cc442008-03-22 10:26:05 +010010232 .unsol_event = alc883_clevo_m720_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010233 .setup = alc883_clevo_m720_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010234 .init_hook = alc883_clevo_m720_init_hook,
Jiang zhe368c7a92008-03-04 11:20:33 +010010235 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020010236 [ALC883_LENOVO_101E_2ch] = {
10237 .mixers = { alc883_lenovo_101e_2ch_mixer},
10238 .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
10239 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10240 .dac_nids = alc883_dac_nids,
Takashi Iwaif9e336f2008-10-31 16:37:07 +010010241 .adc_nids = alc883_adc_nids_alt,
10242 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
Takashi Iwai035eb0c2009-12-17 15:00:26 +010010243 .capsrc_nids = alc883_capsrc_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020010244 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10245 .channel_mode = alc883_3ST_2ch_modes,
10246 .input_mux = &alc883_lenovo_101e_capture_source,
10247 .unsol_event = alc883_lenovo_101e_unsol_event,
10248 .init_hook = alc883_lenovo_101e_all_automute,
10249 },
Kailang Yang272a5272007-05-14 11:00:38 +020010250 [ALC883_LENOVO_NB0763] = {
10251 .mixers = { alc883_lenovo_nb0763_mixer },
10252 .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
10253 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10254 .dac_nids = alc883_dac_nids,
Kailang Yang272a5272007-05-14 11:00:38 +020010255 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10256 .channel_mode = alc883_3ST_2ch_modes,
10257 .need_dac_fix = 1,
10258 .input_mux = &alc883_lenovo_nb0763_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010259 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010260 .setup = alc883_medion_md2_setup,
10261 .init_hook = alc_automute_amp,
Kailang Yang272a5272007-05-14 11:00:38 +020010262 },
10263 [ALC888_LENOVO_MS7195_DIG] = {
10264 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10265 .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
10266 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10267 .dac_nids = alc883_dac_nids,
10268 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang272a5272007-05-14 11:00:38 +020010269 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10270 .channel_mode = alc883_3ST_6ch_modes,
10271 .need_dac_fix = 1,
10272 .input_mux = &alc883_capture_source,
10273 .unsol_event = alc883_lenovo_ms7195_unsol_event,
10274 .init_hook = alc888_lenovo_ms7195_front_automute,
Kailang Yang189609a2007-08-20 11:31:23 +020010275 },
10276 [ALC883_HAIER_W66] = {
Sasha Alexandrc2592492009-06-16 14:52:54 -040010277 .mixers = { alc883_targa_2ch_mixer},
Kailang Yang189609a2007-08-20 11:31:23 +020010278 .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
10279 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10280 .dac_nids = alc883_dac_nids,
10281 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yang189609a2007-08-20 11:31:23 +020010282 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10283 .channel_mode = alc883_3ST_2ch_modes,
10284 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010285 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010286 .setup = alc883_haier_w66_setup,
10287 .init_hook = alc_automute_amp,
Herton Ronaldo Krzesinskieea64192008-03-20 12:14:59 +010010288 },
Claudio Matsuoka4723c022007-07-13 14:36:19 +020010289 [ALC888_3ST_HP] = {
Herton Ronaldo Krzesinskieea64192008-03-20 12:14:59 +010010290 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
Claudio Matsuoka4723c022007-07-13 14:36:19 +020010291 .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
Claudio Matsuoka8341de62007-07-06 12:10:45 +020010292 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10293 .dac_nids = alc883_dac_nids,
Claudio Matsuoka4723c022007-07-13 14:36:19 +020010294 .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
10295 .channel_mode = alc888_3st_hp_modes,
Claudio Matsuoka8341de62007-07-06 12:10:45 +020010296 .need_dac_fix = 1,
10297 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010298 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010299 .setup = alc888_3st_hp_setup,
10300 .init_hook = alc_automute_amp,
Claudio Matsuoka8341de62007-07-06 12:10:45 +020010301 },
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +010010302 [ALC888_6ST_DELL] = {
Herton Ronaldo Krzesinskif24dbdc2008-03-20 12:14:28 +010010303 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +010010304 .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
10305 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10306 .dac_nids = alc883_dac_nids,
10307 .dig_out_nid = ALC883_DIGOUT_NID,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +010010308 .dig_in_nid = ALC883_DIGIN_NID,
10309 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10310 .channel_mode = alc883_sixstack_modes,
10311 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010312 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010313 .setup = alc888_6st_dell_setup,
10314 .init_hook = alc_automute_amp,
Claudio Matsuoka5795b9e2008-01-13 11:58:27 +010010315 },
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +010010316 [ALC883_MITAC] = {
10317 .mixers = { alc883_mitac_mixer },
10318 .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
10319 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10320 .dac_nids = alc883_dac_nids,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +010010321 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10322 .channel_mode = alc883_3ST_2ch_modes,
10323 .input_mux = &alc883_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010324 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010325 .setup = alc883_mitac_setup,
10326 .init_hook = alc_automute_amp,
Andy Shevchenkoa8848bd2007-12-13 17:32:26 +010010327 },
Jiang zhefb97dc62008-03-06 11:07:11 +010010328 [ALC883_FUJITSU_PI2515] = {
10329 .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
10330 .init_verbs = { alc883_init_verbs,
10331 alc883_2ch_fujitsu_pi2515_verbs},
10332 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10333 .dac_nids = alc883_dac_nids,
10334 .dig_out_nid = ALC883_DIGOUT_NID,
10335 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10336 .channel_mode = alc883_3ST_2ch_modes,
10337 .input_mux = &alc883_fujitsu_pi2515_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010338 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010339 .setup = alc883_2ch_fujitsu_pi2515_setup,
10340 .init_hook = alc_automute_amp,
Jiang zhefb97dc62008-03-06 11:07:11 +010010341 },
Vincent Petryef8ef5f2008-11-23 11:31:41 +080010342 [ALC888_FUJITSU_XA3530] = {
10343 .mixers = { alc888_base_mixer, alc883_chmode_mixer },
10344 .init_verbs = { alc883_init_verbs,
10345 alc888_fujitsu_xa3530_verbs },
10346 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10347 .dac_nids = alc883_dac_nids,
10348 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
10349 .adc_nids = alc883_adc_nids_rev,
10350 .capsrc_nids = alc883_capsrc_nids_rev,
10351 .dig_out_nid = ALC883_DIGOUT_NID,
10352 .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
10353 .channel_mode = alc888_4ST_8ch_intel_modes,
10354 .num_mux_defs =
10355 ARRAY_SIZE(alc888_2_capture_sources),
10356 .input_mux = alc888_2_capture_sources,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010357 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010358 .setup = alc888_fujitsu_xa3530_setup,
10359 .init_hook = alc_automute_amp,
Vincent Petryef8ef5f2008-11-23 11:31:41 +080010360 },
Kailang Yange2757d52008-08-26 13:17:46 +020010361 [ALC888_LENOVO_SKY] = {
10362 .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
10363 .init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
10364 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10365 .dac_nids = alc883_dac_nids,
10366 .dig_out_nid = ALC883_DIGOUT_NID,
Kailang Yange2757d52008-08-26 13:17:46 +020010367 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10368 .channel_mode = alc883_sixstack_modes,
10369 .need_dac_fix = 1,
10370 .input_mux = &alc883_lenovo_sky_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010371 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010372 .setup = alc888_lenovo_sky_setup,
10373 .init_hook = alc_automute_amp,
Kailang Yange2757d52008-08-26 13:17:46 +020010374 },
10375 [ALC888_ASUS_M90V] = {
10376 .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
10377 .init_verbs = { alc883_init_verbs, alc888_asus_m90v_verbs },
10378 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10379 .dac_nids = alc883_dac_nids,
10380 .dig_out_nid = ALC883_DIGOUT_NID,
10381 .dig_in_nid = ALC883_DIGIN_NID,
10382 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
10383 .channel_mode = alc883_3ST_6ch_modes,
10384 .need_dac_fix = 1,
10385 .input_mux = &alc883_fujitsu_pi2515_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010386 .unsol_event = alc_sku_unsol_event,
10387 .setup = alc883_mode2_setup,
10388 .init_hook = alc_inithook,
Kailang Yange2757d52008-08-26 13:17:46 +020010389 },
10390 [ALC888_ASUS_EEE1601] = {
10391 .mixers = { alc883_asus_eee1601_mixer },
Takashi Iwaif9e336f2008-10-31 16:37:07 +010010392 .cap_mixer = alc883_asus_eee1601_cap_mixer,
Kailang Yange2757d52008-08-26 13:17:46 +020010393 .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
10394 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10395 .dac_nids = alc883_dac_nids,
10396 .dig_out_nid = ALC883_DIGOUT_NID,
10397 .dig_in_nid = ALC883_DIGIN_NID,
10398 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10399 .channel_mode = alc883_3ST_2ch_modes,
10400 .need_dac_fix = 1,
10401 .input_mux = &alc883_asus_eee1601_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020010402 .unsol_event = alc_sku_unsol_event,
Kailang Yange2757d52008-08-26 13:17:46 +020010403 .init_hook = alc883_eee1601_inithook,
10404 },
Wu Fengguang3ab90932008-11-17 09:51:09 +010010405 [ALC1200_ASUS_P5Q] = {
10406 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
10407 .init_verbs = { alc883_init_verbs },
10408 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10409 .dac_nids = alc883_dac_nids,
10410 .dig_out_nid = ALC1200_DIGOUT_NID,
10411 .dig_in_nid = ALC883_DIGIN_NID,
Wu Fengguangb25c9da2009-02-06 15:02:27 +080010412 .slave_dig_outs = alc1200_slave_dig_outs,
Wu Fengguang3ab90932008-11-17 09:51:09 +010010413 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
10414 .channel_mode = alc883_sixstack_modes,
10415 .input_mux = &alc883_capture_source,
10416 },
Torben Schulzeb4c41d2009-05-18 15:02:35 +020010417 [ALC889A_MB31] = {
10418 .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
10419 .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
10420 alc880_gpio1_init_verbs },
10421 .adc_nids = alc883_adc_nids,
10422 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
Takashi Iwai035eb0c2009-12-17 15:00:26 +010010423 .capsrc_nids = alc883_capsrc_nids,
Torben Schulzeb4c41d2009-05-18 15:02:35 +020010424 .dac_nids = alc883_dac_nids,
10425 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10426 .channel_mode = alc889A_mb31_6ch_modes,
10427 .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
10428 .input_mux = &alc889A_mb31_capture_source,
10429 .dig_out_nid = ALC883_DIGOUT_NID,
10430 .unsol_event = alc889A_mb31_unsol_event,
10431 .init_hook = alc889A_mb31_automute,
10432 },
Guido Günther3e1647c2009-06-05 00:47:26 +020010433 [ALC883_SONY_VAIO_TT] = {
10434 .mixers = { alc883_vaiott_mixer },
10435 .init_verbs = { alc883_init_verbs, alc883_vaiott_verbs },
10436 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
10437 .dac_nids = alc883_dac_nids,
10438 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
10439 .channel_mode = alc883_3ST_2ch_modes,
10440 .input_mux = &alc883_capture_source,
10441 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020010442 .setup = alc883_vaiott_setup,
10443 .init_hook = alc_automute_amp,
Guido Günther3e1647c2009-06-05 00:47:26 +020010444 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010445};
10446
10447
10448/*
Takashi Iwai49535502009-06-30 15:28:30 +020010449 * Pin config fixes
10450 */
10451enum {
Takashi Iwai954a29c2010-07-30 10:55:44 +020010452 PINFIX_ABIT_AW9D_MAX,
10453 PINFIX_PB_M5210,
Takashi Iwai49535502009-06-30 15:28:30 +020010454};
10455
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010456static const struct alc_fixup alc882_fixups[] = {
10457 [PINFIX_ABIT_AW9D_MAX] = {
Takashi Iwai73413b12010-08-30 09:39:57 +020010458 .pins = (const struct alc_pincfg[]) {
10459 { 0x15, 0x01080104 }, /* side */
10460 { 0x16, 0x01011012 }, /* rear */
10461 { 0x17, 0x01016011 }, /* clfe */
10462 { }
10463 }
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010464 },
Takashi Iwai954a29c2010-07-30 10:55:44 +020010465 [PINFIX_PB_M5210] = {
Takashi Iwai73413b12010-08-30 09:39:57 +020010466 .verbs = (const struct hda_verb[]) {
10467 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
10468 {}
10469 }
Takashi Iwai954a29c2010-07-30 10:55:44 +020010470 },
Takashi Iwai49535502009-06-30 15:28:30 +020010471};
10472
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020010473static struct snd_pci_quirk alc882_fixup_tbl[] = {
Takashi Iwai954a29c2010-07-30 10:55:44 +020010474 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
Takashi Iwai49535502009-06-30 15:28:30 +020010475 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
10476 {}
10477};
10478
10479/*
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010480 * BIOS auto configuration
10481 */
Takashi Iwai05f5f472009-08-25 13:10:18 +020010482static int alc882_auto_create_input_ctls(struct hda_codec *codec,
10483 const struct auto_pin_cfg *cfg)
10484{
10485 return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x23, 0x22);
10486}
10487
Takashi Iwai49535502009-06-30 15:28:30 +020010488static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010489 hda_nid_t nid, int pin_type,
Takashi Iwai489008c2010-04-07 09:06:00 +020010490 hda_nid_t dac)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010491{
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010492 int idx;
10493
Takashi Iwai489008c2010-04-07 09:06:00 +020010494 /* set as output */
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010495 alc_set_pin_output(codec, nid, pin_type);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010496
Takashi Iwai489008c2010-04-07 09:06:00 +020010497 if (dac == 0x25)
10498 idx = 4;
10499 else if (dac >= 0x02 && dac <= 0x05)
10500 idx = dac - 2;
10501 else
10502 return;
10503 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010504}
10505
Takashi Iwai49535502009-06-30 15:28:30 +020010506static void alc882_auto_init_multi_out(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010507{
10508 struct alc_spec *spec = codec->spec;
10509 int i;
10510
10511 for (i = 0; i <= HDA_SIDE; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010512 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020010513 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010514 if (nid)
Takashi Iwai49535502009-06-30 15:28:30 +020010515 alc882_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai489008c2010-04-07 09:06:00 +020010516 spec->multiout.dac_nids[i]);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010517 }
10518}
10519
Takashi Iwai49535502009-06-30 15:28:30 +020010520static void alc882_auto_init_hp_out(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010521{
10522 struct alc_spec *spec = codec->spec;
Takashi Iwai489008c2010-04-07 09:06:00 +020010523 hda_nid_t pin, dac;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010524
Takashi Iwaieb06ed82006-09-20 17:10:27 +020010525 pin = spec->autocfg.hp_pins[0];
Takashi Iwai489008c2010-04-07 09:06:00 +020010526 if (pin) {
10527 dac = spec->multiout.hp_nid;
10528 if (!dac)
10529 dac = spec->multiout.dac_nids[0]; /* to front */
10530 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
10531 }
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010532 pin = spec->autocfg.speaker_pins[0];
Takashi Iwai489008c2010-04-07 09:06:00 +020010533 if (pin) {
10534 dac = spec->multiout.extra_out_nid[0];
10535 if (!dac)
10536 dac = spec->multiout.dac_nids[0]; /* to front */
10537 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
10538 }
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010539}
10540
Takashi Iwai49535502009-06-30 15:28:30 +020010541static void alc882_auto_init_analog_input(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010542{
10543 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +020010544 struct auto_pin_cfg *cfg = &spec->autocfg;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010545 int i;
10546
Takashi Iwai66ceeb62010-08-30 13:05:52 +020010547 for (i = 0; i < cfg->num_inputs; i++) {
10548 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai0d971c92009-06-30 16:11:11 +020010549 alc_set_input_pin(codec, nid, i);
Takashi Iwai49535502009-06-30 15:28:30 +020010550 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
10551 snd_hda_codec_write(codec, nid, 0,
10552 AC_VERB_SET_AMP_GAIN_MUTE,
10553 AMP_OUT_MUTE);
10554 }
10555}
10556
10557static void alc882_auto_init_input_src(struct hda_codec *codec)
10558{
10559 struct alc_spec *spec = codec->spec;
10560 int c;
10561
10562 for (c = 0; c < spec->num_adc_nids; c++) {
10563 hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
10564 hda_nid_t nid = spec->capsrc_nids[c];
10565 unsigned int mux_idx;
10566 const struct hda_input_mux *imux;
10567 int conns, mute, idx, item;
10568
10569 conns = snd_hda_get_connections(codec, nid, conn_list,
10570 ARRAY_SIZE(conn_list));
10571 if (conns < 0)
10572 continue;
10573 mux_idx = c >= spec->num_mux_defs ? 0 : c;
10574 imux = &spec->input_mux[mux_idx];
Takashi Iwai53111142010-03-08 12:13:07 +010010575 if (!imux->num_items && mux_idx > 0)
10576 imux = &spec->input_mux[0];
Takashi Iwai49535502009-06-30 15:28:30 +020010577 for (idx = 0; idx < conns; idx++) {
10578 /* if the current connection is the selected one,
10579 * unmute it as default - otherwise mute it
10580 */
10581 mute = AMP_IN_MUTE(idx);
10582 for (item = 0; item < imux->num_items; item++) {
10583 if (imux->items[item].index == idx) {
10584 if (spec->cur_mux[c] == item)
10585 mute = AMP_IN_UNMUTE(idx);
10586 break;
10587 }
10588 }
10589 /* check if we have a selector or mixer
10590 * we could check for the widget type instead, but
10591 * just check for Amp-In presence (in case of mixer
10592 * without amp-in there is something wrong, this
10593 * function shouldn't be used or capsrc nid is wrong)
10594 */
10595 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010596 snd_hda_codec_write(codec, nid, 0,
10597 AC_VERB_SET_AMP_GAIN_MUTE,
Takashi Iwai49535502009-06-30 15:28:30 +020010598 mute);
10599 else if (mute != AMP_IN_MUTE(idx))
10600 snd_hda_codec_write(codec, nid, 0,
10601 AC_VERB_SET_CONNECT_SEL,
10602 idx);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010603 }
10604 }
10605}
10606
Takashi Iwai49535502009-06-30 15:28:30 +020010607/* add mic boosts if needed */
10608static int alc_auto_add_mic_boost(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010609{
10610 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +020010611 struct auto_pin_cfg *cfg = &spec->autocfg;
10612 int i, err;
Takashi Iwai49535502009-06-30 15:28:30 +020010613 hda_nid_t nid;
10614
Takashi Iwai66ceeb62010-08-30 13:05:52 +020010615 for (i = 0; i < cfg->num_inputs; i++) {
10616 if (cfg->inputs[i].type > AUTO_PIN_FRONT_MIC)
10617 break;
10618 nid = cfg->inputs[i].pin;
10619 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
10620 char label[32];
10621 snprintf(label, sizeof(label), "%s Boost",
10622 snd_hda_get_input_pin_label(cfg, i));
10623 err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0,
Takashi Iwai49535502009-06-30 15:28:30 +020010624 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
Takashi Iwai66ceeb62010-08-30 13:05:52 +020010625 if (err < 0)
10626 return err;
10627 }
Takashi Iwai49535502009-06-30 15:28:30 +020010628 }
10629 return 0;
10630}
10631
10632/* almost identical with ALC880 parser... */
10633static int alc882_parse_auto_config(struct hda_codec *codec)
10634{
10635 struct alc_spec *spec = codec->spec;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010636 static hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai757899a2010-07-30 10:48:14 +020010637 int err;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010638
Takashi Iwai05f5f472009-08-25 13:10:18 +020010639 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
10640 alc882_ignore);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010641 if (err < 0)
10642 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010643 if (!spec->autocfg.line_outs)
10644 return 0; /* can't find valid BIOS pin config */
10645
10646 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
10647 if (err < 0)
10648 return err;
10649 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
10650 if (err < 0)
10651 return err;
Takashi Iwai489008c2010-04-07 09:06:00 +020010652 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
10653 "Headphone");
10654 if (err < 0)
10655 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010656 err = alc880_auto_create_extra_out(spec,
10657 spec->autocfg.speaker_pins[0],
10658 "Speaker");
10659 if (err < 0)
10660 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020010661 err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
10662 if (err < 0)
10663 return err;
10664
10665 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
10666
Takashi Iwai757899a2010-07-30 10:48:14 +020010667 alc_auto_parse_digital(codec);
Takashi Iwai05f5f472009-08-25 13:10:18 +020010668
10669 if (spec->kctls.list)
10670 add_mixer(spec, spec->kctls.list);
10671
10672 add_verb(spec, alc883_auto_init_verbs);
10673 /* if ADC 0x07 is available, initialize it, too */
10674 if (get_wcaps_type(get_wcaps(codec, 0x07)) == AC_WID_AUD_IN)
10675 add_verb(spec, alc882_adc1_init_verbs);
10676
10677 spec->num_mux_defs = 1;
10678 spec->input_mux = &spec->private_imux[0];
10679
Kailang Yang6227cdc2010-02-25 08:36:52 +010010680 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai776e1842007-08-29 15:07:11 +020010681
10682 err = alc_auto_add_mic_boost(codec);
10683 if (err < 0)
10684 return err;
10685
Takashi Iwai776e1842007-08-29 15:07:11 +020010686 return 1; /* config found */
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010687}
10688
10689/* additional initialization for auto-configuration model */
Takashi Iwai49535502009-06-30 15:28:30 +020010690static void alc882_auto_init(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010691{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010692 struct alc_spec *spec = codec->spec;
Takashi Iwai49535502009-06-30 15:28:30 +020010693 alc882_auto_init_multi_out(codec);
10694 alc882_auto_init_hp_out(codec);
10695 alc882_auto_init_analog_input(codec);
10696 alc882_auto_init_input_src(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +020010697 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010010698 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020010699 alc_inithook(codec);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010700}
10701
Takashi Iwai49535502009-06-30 15:28:30 +020010702static int patch_alc882(struct hda_codec *codec)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010703{
10704 struct alc_spec *spec;
10705 int err, board_config;
10706
10707 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
10708 if (spec == NULL)
10709 return -ENOMEM;
10710
10711 codec->spec = spec;
10712
Kailang Yangda00c242010-03-19 11:23:45 +010010713 alc_auto_parse_customize_define(codec);
10714
Takashi Iwai49535502009-06-30 15:28:30 +020010715 switch (codec->vendor_id) {
10716 case 0x10ec0882:
10717 case 0x10ec0885:
10718 break;
10719 default:
10720 /* ALC883 and variants */
10721 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
10722 break;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010723 }
10724
Takashi Iwai49535502009-06-30 15:28:30 +020010725 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
10726 alc882_models,
10727 alc882_cfg_tbl);
10728
10729 if (board_config < 0 || board_config >= ALC882_MODEL_LAST)
10730 board_config = snd_hda_check_board_codec_sid_config(codec,
10731 ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
10732
10733 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020010734 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
Takashi Iwai49535502009-06-30 15:28:30 +020010735 codec->chip_name);
10736 board_config = ALC882_AUTO;
10737 }
10738
Takashi Iwai7fa90e82010-04-12 08:49:00 +020010739 if (board_config == ALC882_AUTO)
10740 alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1);
Takashi Iwai49535502009-06-30 15:28:30 +020010741
10742 if (board_config == ALC882_AUTO) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010743 /* automatic parse from the BIOS config */
Takashi Iwai49535502009-06-30 15:28:30 +020010744 err = alc882_parse_auto_config(codec);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010745 if (err < 0) {
10746 alc_free(codec);
10747 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020010748 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010749 printk(KERN_INFO
10750 "hda_codec: Cannot set up configuration "
10751 "from BIOS. Using base mode...\n");
Takashi Iwai49535502009-06-30 15:28:30 +020010752 board_config = ALC882_3ST_DIG;
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010753 }
10754 }
10755
Takashi Iwaidc1eae22010-07-29 15:30:02 +020010756 if (has_cdefine_beep(codec)) {
Takashi Iwai8af25912010-07-28 17:37:16 +020010757 err = snd_hda_attach_beep_device(codec, 0x1);
10758 if (err < 0) {
10759 alc_free(codec);
10760 return err;
10761 }
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090010762 }
10763
Takashi Iwai49535502009-06-30 15:28:30 +020010764 if (board_config != ALC882_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020010765 setup_preset(codec, &alc882_presets[board_config]);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010766
Takashi Iwai49535502009-06-30 15:28:30 +020010767 spec->stream_analog_playback = &alc882_pcm_analog_playback;
10768 spec->stream_analog_capture = &alc882_pcm_analog_capture;
10769 /* FIXME: setup DAC5 */
10770 /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
10771 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
10772
10773 spec->stream_digital_playback = &alc882_pcm_digital_playback;
10774 spec->stream_digital_capture = &alc882_pcm_digital_capture;
10775
Takashi Iwai49535502009-06-30 15:28:30 +020010776 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010777 int i, j;
Takashi Iwai49535502009-06-30 15:28:30 +020010778 spec->num_adc_nids = 0;
10779 for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010780 const struct hda_input_mux *imux = spec->input_mux;
Takashi Iwai49535502009-06-30 15:28:30 +020010781 hda_nid_t cap;
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010782 hda_nid_t items[16];
Takashi Iwai49535502009-06-30 15:28:30 +020010783 hda_nid_t nid = alc882_adc_nids[i];
10784 unsigned int wcap = get_wcaps(codec, nid);
10785 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020010786 wcap = get_wcaps_type(wcap);
Takashi Iwai49535502009-06-30 15:28:30 +020010787 if (wcap != AC_WID_AUD_IN)
10788 continue;
10789 spec->private_adc_nids[spec->num_adc_nids] = nid;
10790 err = snd_hda_get_connections(codec, nid, &cap, 1);
10791 if (err < 0)
10792 continue;
Takashi Iwaid11f74c2009-12-08 12:52:47 +010010793 err = snd_hda_get_connections(codec, cap, items,
10794 ARRAY_SIZE(items));
10795 if (err < 0)
10796 continue;
10797 for (j = 0; j < imux->num_items; j++)
10798 if (imux->items[j].index >= err)
10799 break;
10800 if (j < imux->num_items)
10801 continue;
Takashi Iwai49535502009-06-30 15:28:30 +020010802 spec->private_capsrc_nids[spec->num_adc_nids] = cap;
10803 spec->num_adc_nids++;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020010804 }
Takashi Iwai49535502009-06-30 15:28:30 +020010805 spec->adc_nids = spec->private_adc_nids;
10806 spec->capsrc_nids = spec->private_capsrc_nids;
Kailang Yang2f893282008-05-27 12:14:47 +020010807 }
10808
Takashi Iwaib59bdf32009-08-11 09:47:30 +020010809 set_capture_mixer(codec);
Kailang Yangda00c242010-03-19 11:23:45 +010010810
Takashi Iwaidc1eae22010-07-29 15:30:02 +020010811 if (has_cdefine_beep(codec))
Kailang Yangda00c242010-03-19 11:23:45 +010010812 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010813
Takashi Iwai7fa90e82010-04-12 08:49:00 +020010814 if (board_config == ALC882_AUTO)
10815 alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0);
10816
Takashi Iwai2134ea42008-01-10 16:53:55 +010010817 spec->vmaster_nid = 0x0c;
10818
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010819 codec->patch_ops = alc_patch_ops;
Takashi Iwai49535502009-06-30 15:28:30 +020010820 if (board_config == ALC882_AUTO)
10821 spec->init_hook = alc882_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020010822#ifdef CONFIG_SND_HDA_POWER_SAVE
10823 if (!spec->loopback.amplist)
Takashi Iwai49535502009-06-30 15:28:30 +020010824 spec->loopback.amplist = alc882_loopbacks;
Takashi Iwaicb53c622007-08-10 17:21:45 +020010825#endif
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010826
10827 return 0;
10828}
10829
Takashi Iwai49535502009-06-30 15:28:30 +020010830
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010831/*
Kailang Yangdf694da2005-12-05 19:42:22 +010010832 * ALC262 support
10833 */
10834
10835#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
10836#define ALC262_DIGIN_NID ALC880_DIGIN_NID
10837
10838#define alc262_dac_nids alc260_dac_nids
10839#define alc262_adc_nids alc882_adc_nids
10840#define alc262_adc_nids_alt alc882_adc_nids_alt
Takashi Iwai88c71a92008-02-14 17:27:17 +010010841#define alc262_capsrc_nids alc882_capsrc_nids
10842#define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
Kailang Yangdf694da2005-12-05 19:42:22 +010010843
10844#define alc262_modes alc260_modes
Takashi Iwaic5f2ea02005-12-06 18:54:31 +010010845#define alc262_capture_source alc882_capture_source
Kailang Yangdf694da2005-12-05 19:42:22 +010010846
Kailang Yang4e555fe2008-08-26 13:05:55 +020010847static hda_nid_t alc262_dmic_adc_nids[1] = {
10848 /* ADC0 */
10849 0x09
10850};
10851
10852static hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
10853
Kailang Yangdf694da2005-12-05 19:42:22 +010010854static struct snd_kcontrol_new alc262_base_mixer[] = {
10855 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10856 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
10857 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10858 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
10859 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10860 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10861 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10862 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010863 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010864 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10865 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010866 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010867 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
10868 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10869 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
10870 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
Kailang Yangdf694da2005-12-05 19:42:22 +010010871 { } /* end */
Takashi Iwai834be882006-03-01 14:16:17 +010010872};
10873
Takashi Iwaice875f02008-01-28 18:17:43 +010010874/* update HP, line and mono-out pins according to the master switch */
10875static void alc262_hp_master_update(struct hda_codec *codec)
10876{
10877 struct alc_spec *spec = codec->spec;
10878 int val = spec->master_sw;
10879
10880 /* HP & line-out */
10881 snd_hda_codec_write_cache(codec, 0x1b, 0,
10882 AC_VERB_SET_PIN_WIDGET_CONTROL,
10883 val ? PIN_HP : 0);
10884 snd_hda_codec_write_cache(codec, 0x15, 0,
10885 AC_VERB_SET_PIN_WIDGET_CONTROL,
10886 val ? PIN_HP : 0);
10887 /* mono (speaker) depending on the HP jack sense */
10888 val = val && !spec->jack_present;
10889 snd_hda_codec_write_cache(codec, 0x16, 0,
10890 AC_VERB_SET_PIN_WIDGET_CONTROL,
10891 val ? PIN_OUT : 0);
10892}
10893
10894static void alc262_hp_bpc_automute(struct hda_codec *codec)
10895{
10896 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +080010897
10898 spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
Takashi Iwaice875f02008-01-28 18:17:43 +010010899 alc262_hp_master_update(codec);
10900}
10901
10902static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)
10903{
10904 if ((res >> 26) != ALC880_HP_EVENT)
10905 return;
10906 alc262_hp_bpc_automute(codec);
10907}
10908
10909static void alc262_hp_wildwest_automute(struct hda_codec *codec)
10910{
10911 struct alc_spec *spec = codec->spec;
Wu Fengguang864f92b2009-11-18 12:38:02 +080010912
10913 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwaice875f02008-01-28 18:17:43 +010010914 alc262_hp_master_update(codec);
10915}
10916
10917static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,
10918 unsigned int res)
10919{
10920 if ((res >> 26) != ALC880_HP_EVENT)
10921 return;
10922 alc262_hp_wildwest_automute(codec);
10923}
10924
Takashi Iwaib72519b2009-05-08 14:31:55 +020010925#define alc262_hp_master_sw_get alc260_hp_master_sw_get
Takashi Iwaice875f02008-01-28 18:17:43 +010010926
10927static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
10928 struct snd_ctl_elem_value *ucontrol)
10929{
10930 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10931 struct alc_spec *spec = codec->spec;
10932 int val = !!*ucontrol->value.integer.value;
10933
10934 if (val == spec->master_sw)
10935 return 0;
10936 spec->master_sw = val;
10937 alc262_hp_master_update(codec);
10938 return 1;
10939}
10940
Takashi Iwaib72519b2009-05-08 14:31:55 +020010941#define ALC262_HP_MASTER_SWITCH \
10942 { \
10943 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
10944 .name = "Master Playback Switch", \
10945 .info = snd_ctl_boolean_mono_info, \
10946 .get = alc262_hp_master_sw_get, \
10947 .put = alc262_hp_master_sw_put, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010010948 }, \
10949 { \
10950 .iface = NID_MAPPING, \
10951 .name = "Master Playback Switch", \
10952 .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \
Takashi Iwaib72519b2009-05-08 14:31:55 +020010953 }
10954
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010010955
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010956static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
Takashi Iwaib72519b2009-05-08 14:31:55 +020010957 ALC262_HP_MASTER_SWITCH,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010958 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10959 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
10960 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Takashi Iwaice875f02008-01-28 18:17:43 +010010961 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
10962 HDA_OUTPUT),
10963 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
10964 HDA_OUTPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010965 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
10966 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010967 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010968 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
10969 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010970 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010971 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
10972 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
10973 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10974 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Takashi Iwai9c7f8522006-06-28 15:08:22 +020010975 HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
10976 HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
10977 { } /* end */
10978};
10979
Kailang Yangcd7509a2007-01-26 18:33:17 +010010980static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
Takashi Iwaib72519b2009-05-08 14:31:55 +020010981 ALC262_HP_MASTER_SWITCH,
Kailang Yangcd7509a2007-01-26 18:33:17 +010010982 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
10983 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
10984 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
10985 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwaice875f02008-01-28 18:17:43 +010010986 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
10987 HDA_OUTPUT),
10988 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
10989 HDA_OUTPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010990 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
10991 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010010992 HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010993 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
10994 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
10995 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
10996 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010010997 { } /* end */
10998};
10999
11000static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
11001 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11002 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwaicc69d122007-02-15 19:29:26 +010011003 HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangcd7509a2007-01-26 18:33:17 +010011004 { } /* end */
11005};
11006
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011007/* mute/unmute internal speaker according to the hp jack and mute state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011008static void alc262_hp_t5735_setup(struct hda_codec *codec)
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011009{
11010 struct alc_spec *spec = codec->spec;
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011011
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020011012 spec->autocfg.hp_pins[0] = 0x15;
Takashi Iwaidc99be42010-01-20 08:35:06 +010011013 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011014}
11015
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011016static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
Takashi Iwai86cd9292008-01-28 18:09:56 +010011017 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11018 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Kailang Yang66d2a9d2007-11-14 12:06:21 +010011019 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11020 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11021 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11022 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11023 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11024 { } /* end */
11025};
11026
11027static struct hda_verb alc262_hp_t5735_verbs[] = {
11028 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11029 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11030
11031 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
11032 { }
11033};
11034
Kailang Yang8c427222008-01-10 13:03:59 +010011035static struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
Takashi Iwaif2f48e12008-01-28 18:14:43 +010011036 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11037 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +010011038 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
11039 HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010011040 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
11041 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
11042 { } /* end */
11043};
11044
11045static struct hda_verb alc262_hp_rp5700_verbs[] = {
11046 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11047 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11048 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11049 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11050 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11051 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11052 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11053 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
11054 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
11055 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
11056 {}
11057};
11058
11059static struct hda_input_mux alc262_hp_rp5700_capture_source = {
11060 .num_items = 1,
11061 .items = {
11062 { "Line", 0x1 },
11063 },
11064};
11065
Takashi Iwai42171c12009-05-08 14:11:43 +020011066/* bind hp and internal speaker mute (with plug check) as master switch */
11067static void alc262_hippo_master_update(struct hda_codec *codec)
11068{
11069 struct alc_spec *spec = codec->spec;
11070 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
11071 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
11072 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
11073 unsigned int mute;
11074
11075 /* HP */
11076 mute = spec->master_sw ? 0 : HDA_AMP_MUTE;
11077 snd_hda_codec_amp_stereo(codec, hp_nid, HDA_OUTPUT, 0,
11078 HDA_AMP_MUTE, mute);
11079 /* mute internal speaker per jack sense */
11080 if (spec->jack_present)
11081 mute = HDA_AMP_MUTE;
11082 if (line_nid)
11083 snd_hda_codec_amp_stereo(codec, line_nid, HDA_OUTPUT, 0,
11084 HDA_AMP_MUTE, mute);
11085 if (speaker_nid && speaker_nid != line_nid)
11086 snd_hda_codec_amp_stereo(codec, speaker_nid, HDA_OUTPUT, 0,
11087 HDA_AMP_MUTE, mute);
11088}
11089
11090#define alc262_hippo_master_sw_get alc262_hp_master_sw_get
11091
11092static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
11093 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai0724ea22007-08-23 00:31:43 +020011094{
11095 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
Takashi Iwai42171c12009-05-08 14:11:43 +020011096 struct alc_spec *spec = codec->spec;
11097 int val = !!*ucontrol->value.integer.value;
Takashi Iwai0724ea22007-08-23 00:31:43 +020011098
Takashi Iwai42171c12009-05-08 14:11:43 +020011099 if (val == spec->master_sw)
11100 return 0;
11101 spec->master_sw = val;
11102 alc262_hippo_master_update(codec);
11103 return 1;
Takashi Iwai0724ea22007-08-23 00:31:43 +020011104}
Takashi Iwai5b319542007-07-26 11:49:22 +020011105
Takashi Iwai42171c12009-05-08 14:11:43 +020011106#define ALC262_HIPPO_MASTER_SWITCH \
11107 { \
11108 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
11109 .name = "Master Playback Switch", \
11110 .info = snd_ctl_boolean_mono_info, \
11111 .get = alc262_hippo_master_sw_get, \
11112 .put = alc262_hippo_master_sw_put, \
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010011113 }, \
11114 { \
11115 .iface = NID_MAPPING, \
11116 .name = "Master Playback Switch", \
11117 .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
11118 (SUBDEV_SPEAKER(0) << 16), \
Takashi Iwai42171c12009-05-08 14:11:43 +020011119 }
11120
11121static struct snd_kcontrol_new alc262_hippo_mixer[] = {
11122 ALC262_HIPPO_MASTER_SWITCH,
11123 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11124 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11125 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11126 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11127 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11128 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11129 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11130 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11131 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11132 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11133 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
11134 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11135 { } /* end */
11136};
11137
11138static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
11139 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11140 ALC262_HIPPO_MASTER_SWITCH,
11141 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11142 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11143 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11144 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11145 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11146 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11147 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11148 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11149 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11150 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
11151 { } /* end */
11152};
11153
11154/* mute/unmute internal speaker according to the hp jack and mute state */
11155static void alc262_hippo_automute(struct hda_codec *codec)
11156{
11157 struct alc_spec *spec = codec->spec;
11158 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
Takashi Iwai42171c12009-05-08 14:11:43 +020011159
Wu Fengguang864f92b2009-11-18 12:38:02 +080011160 spec->jack_present = snd_hda_jack_detect(codec, hp_nid);
Takashi Iwai42171c12009-05-08 14:11:43 +020011161 alc262_hippo_master_update(codec);
11162}
11163
11164static void alc262_hippo_unsol_event(struct hda_codec *codec, unsigned int res)
11165{
11166 if ((res >> 26) != ALC880_HP_EVENT)
11167 return;
11168 alc262_hippo_automute(codec);
11169}
11170
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011171static void alc262_hippo_setup(struct hda_codec *codec)
Takashi Iwai42171c12009-05-08 14:11:43 +020011172{
11173 struct alc_spec *spec = codec->spec;
11174
11175 spec->autocfg.hp_pins[0] = 0x15;
11176 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai42171c12009-05-08 14:11:43 +020011177}
11178
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011179static void alc262_hippo1_setup(struct hda_codec *codec)
Takashi Iwai42171c12009-05-08 14:11:43 +020011180{
11181 struct alc_spec *spec = codec->spec;
11182
11183 spec->autocfg.hp_pins[0] = 0x1b;
11184 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai42171c12009-05-08 14:11:43 +020011185}
11186
11187
Kailang Yang272a5272007-05-14 11:00:38 +020011188static struct snd_kcontrol_new alc262_sony_mixer[] = {
Takashi Iwai0724ea22007-08-23 00:31:43 +020011189 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
Takashi Iwai42171c12009-05-08 14:11:43 +020011190 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang272a5272007-05-14 11:00:38 +020011191 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("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11194 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11195 { } /* end */
11196};
11197
Kailang Yang83c34212007-07-05 11:43:05 +020011198static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020011199 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11200 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang83c34212007-07-05 11:43:05 +020011201 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11202 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("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11205 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11206 { } /* end */
11207};
Kailang Yang272a5272007-05-14 11:00:38 +020011208
Tony Vroonba340e82009-02-02 19:01:30 +000011209static struct snd_kcontrol_new alc262_tyan_mixer[] = {
11210 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11211 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
11212 HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
11213 HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
11214 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
11215 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
11216 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11217 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11218 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11219 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11220 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11221 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
11222 { } /* end */
11223};
11224
11225static struct hda_verb alc262_tyan_verbs[] = {
11226 /* Headphone automute */
11227 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11228 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11229 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11230
11231 /* P11 AUX_IN, white 4-pin connector */
11232 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11233 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
11234 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
11235 {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
11236
11237 {}
11238};
11239
11240/* unsolicited event for HP jack sensing */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011241static void alc262_tyan_setup(struct hda_codec *codec)
Tony Vroonba340e82009-02-02 19:01:30 +000011242{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020011243 struct alc_spec *spec = codec->spec;
Tony Vroonba340e82009-02-02 19:01:30 +000011244
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020011245 spec->autocfg.hp_pins[0] = 0x1b;
11246 spec->autocfg.speaker_pins[0] = 0x15;
Tony Vroonba340e82009-02-02 19:01:30 +000011247}
11248
Tony Vroonba340e82009-02-02 19:01:30 +000011249
Kailang Yangdf694da2005-12-05 19:42:22 +010011250#define alc262_capture_mixer alc882_capture_mixer
11251#define alc262_capture_alt_mixer alc882_capture_alt_mixer
11252
11253/*
11254 * generic initialization of ADC, input mixers and output mixers
11255 */
11256static struct hda_verb alc262_init_verbs[] = {
11257 /*
11258 * Unmute ADC0-2 and set the default input to mic-in
11259 */
11260 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11261 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11262 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11263 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11264 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11265 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11266
Takashi Iwaicb53c622007-08-10 17:21:45 +020011267 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangdf694da2005-12-05 19:42:22 +010011268 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011269 * Note: PASD motherboards uses the Line In 2 as the input for
11270 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +010011271 */
11272 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011273 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11274 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11275 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11276 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11277 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +010011278
11279 /*
11280 * Set up output mixers (0x0c - 0x0e)
11281 */
11282 /* set vol=0 to output mixers */
11283 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11284 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11285 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11286 /* set up input amps for analog loopback */
11287 /* Amp Indices: DAC = 0, mixer = 1 */
11288 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11289 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11290 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11291 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11292 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11293 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11294
11295 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
11296 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11297 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
11298 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11299 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11300 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
11301
11302 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11303 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11304 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11305 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11306 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
Kailang Yangea1fb292008-08-26 12:58:38 +020011307
Kailang Yangdf694da2005-12-05 19:42:22 +010011308 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
11309 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
Kailang Yangea1fb292008-08-26 12:58:38 +020011310
Kailang Yangdf694da2005-12-05 19:42:22 +010011311 /* FIXME: use matrix-type input source selection */
11312 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11313 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11314 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11315 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11316 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11317 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11318 /* Input mixer2 */
11319 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11320 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11321 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11322 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11323 /* Input mixer3 */
11324 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11325 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11326 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011327 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
Kailang Yangdf694da2005-12-05 19:42:22 +010011328
11329 { }
11330};
11331
Kailang Yang4e555fe2008-08-26 13:05:55 +020011332static struct hda_verb alc262_eapd_verbs[] = {
11333 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
11334 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
11335 { }
11336};
11337
Kailang Yangccc656c2006-10-17 12:32:26 +020011338static struct hda_verb alc262_hippo1_unsol_verbs[] = {
11339 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11340 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
11341 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
11342
11343 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11344 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11345 {}
11346};
11347
Kailang Yang272a5272007-05-14 11:00:38 +020011348static struct hda_verb alc262_sony_unsol_verbs[] = {
11349 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
11350 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11351 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
11352
11353 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11354 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Akio Idehara7b1e8792008-06-09 22:46:07 +090011355 {}
Kailang Yang272a5272007-05-14 11:00:38 +020011356};
11357
Kailang Yang4e555fe2008-08-26 13:05:55 +020011358static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
11359 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11360 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
11361 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11362 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11363 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yang4e555fe2008-08-26 13:05:55 +020011364 { } /* end */
11365};
11366
11367static struct hda_verb alc262_toshiba_s06_verbs[] = {
11368 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
11369 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11370 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11371 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11372 {0x22, AC_VERB_SET_CONNECT_SEL, 0x09},
11373 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11374 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
11375 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11376 {}
11377};
11378
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011379static void alc262_toshiba_s06_setup(struct hda_codec *codec)
Kailang Yang4e555fe2008-08-26 13:05:55 +020011380{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020011381 struct alc_spec *spec = codec->spec;
11382
11383 spec->autocfg.hp_pins[0] = 0x15;
11384 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020011385 spec->ext_mic.pin = 0x18;
11386 spec->ext_mic.mux_idx = 0;
11387 spec->int_mic.pin = 0x12;
11388 spec->int_mic.mux_idx = 9;
11389 spec->auto_mic = 1;
Kailang Yang4e555fe2008-08-26 13:05:55 +020011390}
11391
Takashi Iwai834be882006-03-01 14:16:17 +010011392/*
Pascal Terjane8f9ae22008-08-04 14:36:05 +020011393 * nec model
11394 * 0x15 = headphone
11395 * 0x16 = internal speaker
11396 * 0x18 = external mic
11397 */
11398
11399static struct snd_kcontrol_new alc262_nec_mixer[] = {
11400 HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
11401 HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
11402
11403 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11404 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11405 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11406
11407 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
11408 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
11409 { } /* end */
11410};
11411
11412static struct hda_verb alc262_nec_verbs[] = {
11413 /* Unmute Speaker */
11414 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
11415
11416 /* Headphone */
11417 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11418 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11419
11420 /* External mic to headphone */
11421 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11422 /* External mic to speaker */
11423 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11424 {}
11425};
11426
11427/*
Takashi Iwai834be882006-03-01 14:16:17 +010011428 * fujitsu model
Tony Vroon5d9fab22008-03-14 17:09:18 +010011429 * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
11430 * 0x1b = port replicator headphone out
Takashi Iwai834be882006-03-01 14:16:17 +010011431 */
11432
11433#define ALC_HP_EVENT 0x37
11434
11435static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
11436 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11437 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Tony Vroon5d9fab22008-03-14 17:09:18 +010011438 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11439 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai834be882006-03-01 14:16:17 +010011440 {}
11441};
11442
Jiang zhe0e31daf2008-03-20 12:12:39 +010011443static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
11444 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
11445 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
11446 {}
11447};
11448
Daniel T Chene2595322009-12-19 18:19:02 -050011449static struct hda_verb alc262_lenovo_3000_init_verbs[] = {
11450 /* Front Mic pin: input vref at 50% */
11451 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
11452 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11453 {}
11454};
11455
Takashi Iwai834be882006-03-01 14:16:17 +010011456static struct hda_input_mux alc262_fujitsu_capture_source = {
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011457 .num_items = 3,
Takashi Iwai834be882006-03-01 14:16:17 +010011458 .items = {
11459 { "Mic", 0x0 },
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011460 { "Int Mic", 0x1 },
Takashi Iwai834be882006-03-01 14:16:17 +010011461 { "CD", 0x4 },
11462 },
11463};
11464
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011465static struct hda_input_mux alc262_HP_capture_source = {
11466 .num_items = 5,
11467 .items = {
11468 { "Mic", 0x0 },
zhejiangaccbe492007-08-31 12:36:05 +020011469 { "Front Mic", 0x1 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011470 { "Line", 0x2 },
11471 { "CD", 0x4 },
11472 { "AUX IN", 0x6 },
11473 },
11474};
11475
zhejiangaccbe492007-08-31 12:36:05 +020011476static struct hda_input_mux alc262_HP_D7000_capture_source = {
11477 .num_items = 4,
11478 .items = {
11479 { "Mic", 0x0 },
11480 { "Front Mic", 0x2 },
11481 { "Line", 0x1 },
11482 { "CD", 0x4 },
11483 },
11484};
11485
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011486/* mute/unmute internal speaker according to the hp jacks and mute state */
Takashi Iwai834be882006-03-01 14:16:17 +010011487static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
11488{
11489 struct alc_spec *spec = codec->spec;
11490 unsigned int mute;
11491
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011492 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011493 spec->jack_present = snd_hda_jack_detect(codec, 0x14) ||
11494 snd_hda_jack_detect(codec, 0x1b);
Takashi Iwai834be882006-03-01 14:16:17 +010011495 spec->sense_updated = 1;
11496 }
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011497 /* unmute internal speaker only if both HPs are unplugged and
11498 * master switch is on
11499 */
11500 if (spec->jack_present)
11501 mute = HDA_AMP_MUTE;
11502 else
Takashi Iwai834be882006-03-01 14:16:17 +010011503 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011504 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
11505 HDA_AMP_MUTE, mute);
Takashi Iwai834be882006-03-01 14:16:17 +010011506}
11507
11508/* unsolicited event for HP jack sensing */
11509static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
11510 unsigned int res)
11511{
11512 if ((res >> 26) != ALC_HP_EVENT)
11513 return;
11514 alc262_fujitsu_automute(codec, 1);
11515}
11516
Takashi Iwaiebc7a402008-05-20 09:23:05 +020011517static void alc262_fujitsu_init_hook(struct hda_codec *codec)
11518{
11519 alc262_fujitsu_automute(codec, 1);
11520}
11521
Takashi Iwai834be882006-03-01 14:16:17 +010011522/* bind volumes of both NID 0x0c and 0x0d */
Takashi Iwaicca3b372007-08-10 17:12:15 +020011523static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
11524 .ops = &snd_hda_bind_vol,
11525 .values = {
11526 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
11527 HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
11528 0
11529 },
11530};
Takashi Iwai834be882006-03-01 14:16:17 +010011531
Jiang zhe0e31daf2008-03-20 12:12:39 +010011532/* mute/unmute internal speaker according to the hp jack and mute state */
11533static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
11534{
11535 struct alc_spec *spec = codec->spec;
11536 unsigned int mute;
11537
11538 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011539 spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
Jiang zhe0e31daf2008-03-20 12:12:39 +010011540 spec->sense_updated = 1;
11541 }
11542 if (spec->jack_present) {
11543 /* mute internal speaker */
11544 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11545 HDA_AMP_MUTE, HDA_AMP_MUTE);
11546 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
11547 HDA_AMP_MUTE, HDA_AMP_MUTE);
11548 } else {
11549 /* unmute internal speaker if necessary */
11550 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
11551 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11552 HDA_AMP_MUTE, mute);
11553 snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
11554 HDA_AMP_MUTE, mute);
11555 }
11556}
11557
11558/* unsolicited event for HP jack sensing */
11559static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
11560 unsigned int res)
11561{
11562 if ((res >> 26) != ALC_HP_EVENT)
11563 return;
11564 alc262_lenovo_3000_automute(codec, 1);
11565}
11566
Takashi Iwai8de56b72009-07-24 16:51:47 +020011567static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
11568 int dir, int idx, long *valp)
11569{
11570 int i, change = 0;
11571
11572 for (i = 0; i < 2; i++, valp++)
11573 change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
11574 HDA_AMP_MUTE,
11575 *valp ? 0 : HDA_AMP_MUTE);
11576 return change;
11577}
11578
Takashi Iwai834be882006-03-01 14:16:17 +010011579/* bind hp and internal speaker mute (with plug check) */
11580static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
11581 struct snd_ctl_elem_value *ucontrol)
11582{
11583 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11584 long *valp = ucontrol->value.integer.value;
11585 int change;
11586
Takashi Iwai8de56b72009-07-24 16:51:47 +020011587 change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
11588 change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
Takashi Iwai82beb8f2007-08-10 17:09:26 +020011589 if (change)
11590 alc262_fujitsu_automute(codec, 0);
Takashi Iwai834be882006-03-01 14:16:17 +010011591 return change;
11592}
11593
11594static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
Takashi Iwaicca3b372007-08-10 17:12:15 +020011595 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
Takashi Iwai834be882006-03-01 14:16:17 +010011596 {
11597 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11598 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010011599 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwai834be882006-03-01 14:16:17 +010011600 .info = snd_hda_mixer_amp_switch_info,
11601 .get = snd_hda_mixer_amp_switch_get,
11602 .put = alc262_fujitsu_master_sw_put,
11603 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
11604 },
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010011605 {
11606 .iface = NID_MAPPING,
11607 .name = "Master Playback Switch",
11608 .private_value = 0x1b,
11609 },
Takashi Iwai834be882006-03-01 14:16:17 +010011610 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11611 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11612 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11613 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11614 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Takashi Iwai39d3ed32007-10-12 15:03:48 +020011615 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
11616 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
11617 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Takashi Iwai834be882006-03-01 14:16:17 +010011618 { } /* end */
11619};
11620
Jiang zhe0e31daf2008-03-20 12:12:39 +010011621/* bind hp and internal speaker mute (with plug check) */
11622static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
11623 struct snd_ctl_elem_value *ucontrol)
11624{
11625 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11626 long *valp = ucontrol->value.integer.value;
11627 int change;
11628
Takashi Iwai8de56b72009-07-24 16:51:47 +020011629 change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
Jiang zhe0e31daf2008-03-20 12:12:39 +010011630 if (change)
11631 alc262_lenovo_3000_automute(codec, 0);
11632 return change;
11633}
11634
11635static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
11636 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
11637 {
11638 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11639 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010011640 .subdevice = HDA_SUBDEV_AMP_FLAG,
Jiang zhe0e31daf2008-03-20 12:12:39 +010011641 .info = snd_hda_mixer_amp_switch_info,
11642 .get = snd_hda_mixer_amp_switch_get,
11643 .put = alc262_lenovo_3000_master_sw_put,
11644 .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
11645 },
11646 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
11647 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
11648 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11649 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11650 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11651 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
11652 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
11653 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
11654 { } /* end */
11655};
11656
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011657static struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
11658 HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
Takashi Iwai42171c12009-05-08 14:11:43 +020011659 ALC262_HIPPO_MASTER_SWITCH,
Hiroshi Miura9f99a632008-08-28 16:09:06 +020011660 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
11661 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
11662 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
11663 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11664 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11665 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
11666 { } /* end */
11667};
11668
Takashi Iwai304dcaa2006-07-25 14:51:16 +020011669/* additional init verbs for Benq laptops */
11670static struct hda_verb alc262_EAPD_verbs[] = {
11671 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
11672 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
11673 {}
11674};
11675
Kailang Yang83c34212007-07-05 11:43:05 +020011676static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
11677 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11678 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
11679
11680 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
11681 {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
11682 {}
11683};
11684
Tobin Davisf651b502007-10-26 12:40:47 +020011685/* Samsung Q1 Ultra Vista model setup */
11686static struct snd_kcontrol_new alc262_ultra_mixer[] = {
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011687 HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
11688 HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
Tobin Davisf651b502007-10-26 12:40:47 +020011689 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
11690 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
11691 HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011692 HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT),
Tobin Davisf651b502007-10-26 12:40:47 +020011693 { } /* end */
11694};
11695
11696static struct hda_verb alc262_ultra_verbs[] = {
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011697 /* output mixer */
11698 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11699 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11700 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11701 /* speaker */
11702 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
11703 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11704 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11705 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
11706 /* HP */
Tobin Davisf651b502007-10-26 12:40:47 +020011707 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011708 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
11709 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11710 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
11711 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
11712 /* internal mic */
11713 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
11714 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11715 /* ADC, choose mic */
11716 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11717 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11718 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11719 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11720 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11721 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11722 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
11723 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
11724 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
11725 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
Tobin Davisf651b502007-10-26 12:40:47 +020011726 {}
11727};
11728
Tobin Davisf651b502007-10-26 12:40:47 +020011729/* mute/unmute internal speaker according to the hp jack and mute state */
11730static void alc262_ultra_automute(struct hda_codec *codec)
11731{
11732 struct alc_spec *spec = codec->spec;
11733 unsigned int mute;
Tobin Davisf651b502007-10-26 12:40:47 +020011734
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011735 mute = 0;
11736 /* auto-mute only when HP is used as HP */
11737 if (!spec->cur_mux[0]) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080011738 spec->jack_present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011739 if (spec->jack_present)
11740 mute = HDA_AMP_MUTE;
Tobin Davisf651b502007-10-26 12:40:47 +020011741 }
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011742 /* mute/unmute internal speaker */
11743 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
11744 HDA_AMP_MUTE, mute);
11745 /* mute/unmute HP */
11746 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
11747 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
Tobin Davisf651b502007-10-26 12:40:47 +020011748}
11749
11750/* unsolicited event for HP jack sensing */
11751static void alc262_ultra_unsol_event(struct hda_codec *codec,
11752 unsigned int res)
11753{
11754 if ((res >> 26) != ALC880_HP_EVENT)
11755 return;
11756 alc262_ultra_automute(codec);
11757}
11758
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011759static struct hda_input_mux alc262_ultra_capture_source = {
11760 .num_items = 2,
11761 .items = {
11762 { "Mic", 0x1 },
11763 { "Headphone", 0x7 },
11764 },
11765};
11766
11767static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
11768 struct snd_ctl_elem_value *ucontrol)
11769{
11770 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
11771 struct alc_spec *spec = codec->spec;
11772 int ret;
11773
Takashi Iwai54cbc9a2008-10-31 15:24:04 +010011774 ret = alc_mux_enum_put(kcontrol, ucontrol);
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011775 if (!ret)
11776 return 0;
11777 /* reprogram the HP pin as mic or HP according to the input source */
11778 snd_hda_codec_write_cache(codec, 0x15, 0,
11779 AC_VERB_SET_PIN_WIDGET_CONTROL,
11780 spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
11781 alc262_ultra_automute(codec); /* mute/unmute HP */
11782 return ret;
11783}
11784
11785static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
11786 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
11787 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
11788 {
11789 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
11790 .name = "Capture Source",
Takashi Iwai54cbc9a2008-10-31 15:24:04 +010011791 .info = alc_mux_enum_info,
11792 .get = alc_mux_enum_get,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011793 .put = alc262_ultra_mux_enum_put,
11794 },
Jaroslav Kysela5b0cb1d2009-12-08 16:13:32 +010011795 {
11796 .iface = NID_MAPPING,
11797 .name = "Capture Source",
11798 .private_value = 0x15,
11799 },
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010011800 { } /* end */
11801};
11802
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011803/* We use two mixers depending on the output pin; 0x16 is a mono output
11804 * and thus it's bound with a different mixer.
11805 * This function returns which mixer amp should be used.
11806 */
11807static int alc262_check_volbit(hda_nid_t nid)
11808{
11809 if (!nid)
11810 return 0;
11811 else if (nid == 0x16)
11812 return 2;
11813 else
11814 return 1;
11815}
11816
11817static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
11818 const char *pfx, int *vbits)
11819{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011820 unsigned long val;
11821 int vbit;
11822
11823 vbit = alc262_check_volbit(nid);
11824 if (!vbit)
11825 return 0;
11826 if (*vbits & vbit) /* a volume control for this mixer already there */
11827 return 0;
11828 *vbits |= vbit;
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011829 if (vbit == 2)
11830 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
11831 else
11832 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
Takashi Iwai0afe5f82009-10-02 09:20:00 +020011833 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val);
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011834}
11835
11836static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
11837 const char *pfx)
11838{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011839 unsigned long val;
11840
11841 if (!nid)
11842 return 0;
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011843 if (nid == 0x16)
11844 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
11845 else
11846 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
Takashi Iwai0afe5f82009-10-02 09:20:00 +020011847 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val);
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011848}
11849
Kailang Yangdf694da2005-12-05 19:42:22 +010011850/* add playback controls from the parsed DAC table */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011851static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
11852 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010011853{
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011854 const char *pfx;
11855 int vbits;
Kailang Yangdf694da2005-12-05 19:42:22 +010011856 int err;
11857
11858 spec->multiout.num_dacs = 1; /* only use one dac */
11859 spec->multiout.dac_nids = spec->private_dac_nids;
11860 spec->multiout.dac_nids[0] = 2;
11861
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011862 if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
11863 pfx = "Master";
11864 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
11865 pfx = "Speaker";
11866 else
11867 pfx = "Front";
11868 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx);
11869 if (err < 0)
11870 return err;
11871 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker");
11872 if (err < 0)
11873 return err;
11874 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone");
11875 if (err < 0)
11876 return err;
Kailang Yangdf694da2005-12-05 19:42:22 +010011877
Takashi Iwaic3fc1f52009-08-25 16:08:47 +020011878 vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
11879 alc262_check_volbit(cfg->speaker_pins[0]) |
11880 alc262_check_volbit(cfg->hp_pins[0]);
11881 if (vbits == 1 || vbits == 2)
11882 pfx = "Master"; /* only one mixer is used */
11883 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
11884 pfx = "Speaker";
11885 else
11886 pfx = "Front";
11887 vbits = 0;
11888 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits);
11889 if (err < 0)
11890 return err;
11891 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker",
11892 &vbits);
11893 if (err < 0)
11894 return err;
11895 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone",
11896 &vbits);
11897 if (err < 0)
11898 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011899 return 0;
Kailang Yangdf694da2005-12-05 19:42:22 +010011900}
11901
Takashi Iwai05f5f472009-08-25 13:10:18 +020011902#define alc262_auto_create_input_ctls \
Takashi Iwaieaa9b3a2010-01-17 13:09:33 +010011903 alc882_auto_create_input_ctls
Kailang Yangdf694da2005-12-05 19:42:22 +010011904
11905/*
11906 * generic initialization of ADC, input mixers and output mixers
11907 */
11908static struct hda_verb alc262_volume_init_verbs[] = {
11909 /*
11910 * Unmute ADC0-2 and set the default input to mic-in
11911 */
11912 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11913 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11914 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11915 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11916 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11917 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11918
Takashi Iwaicb53c622007-08-10 17:21:45 +020011919 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangdf694da2005-12-05 19:42:22 +010011920 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011921 * Note: PASD motherboards uses the Line In 2 as the input for
11922 * front panel mic (mic 2)
Kailang Yangdf694da2005-12-05 19:42:22 +010011923 */
11924 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011925 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11926 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11927 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11928 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11929 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Kailang Yangdf694da2005-12-05 19:42:22 +010011930
11931 /*
11932 * Set up output mixers (0x0c - 0x0f)
11933 */
11934 /* set vol=0 to output mixers */
11935 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11936 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11937 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yangea1fb292008-08-26 12:58:38 +020011938
Kailang Yangdf694da2005-12-05 19:42:22 +010011939 /* set up input amps for analog loopback */
11940 /* Amp Indices: DAC = 0, mixer = 1 */
11941 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11942 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11943 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11944 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11945 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11946 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
11947
11948 /* FIXME: use matrix-type input source selection */
11949 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
11950 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
11951 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11952 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11953 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11954 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11955 /* Input mixer2 */
11956 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11957 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11958 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11959 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11960 /* Input mixer3 */
11961 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
11962 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
11963 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
11964 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
11965
11966 { }
11967};
11968
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011969static struct hda_verb alc262_HP_BPC_init_verbs[] = {
11970 /*
11971 * Unmute ADC0-2 and set the default input to mic-in
11972 */
11973 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
11974 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11975 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
11976 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11977 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
11978 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
11979
Takashi Iwaicb53c622007-08-10 17:21:45 +020011980 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011981 * mixer widget
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020011982 * Note: PASD motherboards uses the Line In 2 as the input for
11983 * front panel mic (mic 2)
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011984 */
11985 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020011986 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
11987 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
11988 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
11989 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
11990 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
11991 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
11992 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
Kailang Yangea1fb292008-08-26 12:58:38 +020011993
Takashi Iwai9c7f8522006-06-28 15:08:22 +020011994 /*
11995 * Set up output mixers (0x0c - 0x0e)
11996 */
11997 /* set vol=0 to output mixers */
11998 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
11999 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12000 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12001
12002 /* set up input amps for analog loopback */
12003 /* Amp Indices: DAC = 0, mixer = 1 */
12004 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12005 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12006 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12007 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12008 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12009 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12010
Takashi Iwaice875f02008-01-28 18:17:43 +010012011 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012012 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12013 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
12014
12015 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12016 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12017
12018 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
12019 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12020
12021 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12022 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12023 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
12024 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12025 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
12026
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020012027 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012028 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12029 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020012030 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012031 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12032 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12033
12034
12035 /* FIXME: use matrix-type input source selection */
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020012036 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 0b, 12 */
12037 /* Input mixer1: only unmute Mic */
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012038 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020012039 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12040 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12041 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12042 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12043 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12044 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12045 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12046 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012047 /* Input mixer2 */
12048 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020012049 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12050 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12051 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12052 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12053 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12054 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12055 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12056 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012057 /* Input mixer3 */
12058 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
Jaroslav Kysela0e4835c2009-05-25 16:44:20 +020012059 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
12060 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
12061 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
12062 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
12063 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
12064 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
12065 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
12066 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012067
Takashi Iwaice875f02008-01-28 18:17:43 +010012068 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12069
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012070 { }
12071};
12072
Kailang Yangcd7509a2007-01-26 18:33:17 +010012073static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
12074 /*
12075 * Unmute ADC0-2 and set the default input to mic-in
12076 */
12077 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
12078 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12079 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
12080 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12081 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
12082 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12083
Takashi Iwaicb53c622007-08-10 17:21:45 +020012084 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
Kailang Yangcd7509a2007-01-26 18:33:17 +010012085 * mixer widget
12086 * Note: PASD motherboards uses the Line In 2 as the input for front
12087 * panel mic (mic 2)
12088 */
12089 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020012090 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
12091 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
12092 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
12093 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
12094 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
12095 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
12096 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
12097 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
Kailang Yangcd7509a2007-01-26 18:33:17 +010012098 /*
12099 * Set up output mixers (0x0c - 0x0e)
12100 */
12101 /* set vol=0 to output mixers */
12102 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12103 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12104 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
12105
12106 /* set up input amps for analog loopback */
12107 /* Amp Indices: DAC = 0, mixer = 1 */
12108 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12109 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12110 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12111 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12112 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
12113 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
12114
12115
12116 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */
12117 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */
12118 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */
12119 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */
12120 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
12121 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */
12122 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */
12123
12124 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12125 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12126
12127 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
12128 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
12129
12130 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
12131 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12132 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12133 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
12134 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12135 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
12136
12137 /* FIXME: use matrix-type input source selection */
12138 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
12139 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
12140 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
12141 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
12142 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
12143 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
12144 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
12145 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12146 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
12147 /* Input mixer2 */
12148 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12149 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
12150 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
12151 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
12152 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
12153 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12154 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
12155 /* Input mixer3 */
12156 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
12157 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
12158 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
12159 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
12160 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
12161 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
12162 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
12163
Takashi Iwaice875f02008-01-28 18:17:43 +010012164 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12165
Kailang Yangcd7509a2007-01-26 18:33:17 +010012166 { }
12167};
12168
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012169static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
12170
12171 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Front Speaker */
12172 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
12173 {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
12174
12175 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* MIC jack */
12176 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
12177 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
12178 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
12179
12180 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP jack */
12181 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
12182 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
12183 {}
12184};
12185
12186
Takashi Iwaicb53c622007-08-10 17:21:45 +020012187#ifdef CONFIG_SND_HDA_POWER_SAVE
12188#define alc262_loopbacks alc880_loopbacks
12189#endif
12190
Sasha Alexandrdef319f2009-06-16 16:00:15 -040012191/* pcm configuration: identical with ALC880 */
Kailang Yangdf694da2005-12-05 19:42:22 +010012192#define alc262_pcm_analog_playback alc880_pcm_analog_playback
12193#define alc262_pcm_analog_capture alc880_pcm_analog_capture
12194#define alc262_pcm_digital_playback alc880_pcm_digital_playback
12195#define alc262_pcm_digital_capture alc880_pcm_digital_capture
12196
12197/*
12198 * BIOS auto configuration
12199 */
12200static int alc262_parse_auto_config(struct hda_codec *codec)
12201{
12202 struct alc_spec *spec = codec->spec;
12203 int err;
12204 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
12205
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012206 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
12207 alc262_ignore);
12208 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010012209 return err;
Takashi Iwaie64f14f2009-01-20 18:32:55 +010012210 if (!spec->autocfg.line_outs) {
Takashi Iwai0852d7a2009-02-11 11:35:15 +010012211 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
Takashi Iwaie64f14f2009-01-20 18:32:55 +010012212 spec->multiout.max_channels = 2;
12213 spec->no_analog = 1;
12214 goto dig_only;
12215 }
Kailang Yangdf694da2005-12-05 19:42:22 +010012216 return 0; /* can't find valid BIOS pin config */
Takashi Iwaie64f14f2009-01-20 18:32:55 +010012217 }
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012218 err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
12219 if (err < 0)
12220 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020012221 err = alc262_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012222 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010012223 return err;
12224
12225 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
12226
Takashi Iwaie64f14f2009-01-20 18:32:55 +010012227 dig_only:
Takashi Iwai757899a2010-07-30 10:48:14 +020012228 alc_auto_parse_digital(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010012229
Takashi Iwai603c4012008-07-30 15:01:44 +020012230 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010012231 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +010012232
Takashi Iwaid88897e2008-10-31 15:01:37 +010012233 add_verb(spec, alc262_volume_init_verbs);
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +020012234 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020012235 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +010012236
Takashi Iwai776e1842007-08-29 15:07:11 +020012237 err = alc_auto_add_mic_boost(codec);
12238 if (err < 0)
12239 return err;
12240
Kailang Yang6227cdc2010-02-25 08:36:52 +010012241 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020012242
Kailang Yangdf694da2005-12-05 19:42:22 +010012243 return 1;
12244}
12245
12246#define alc262_auto_init_multi_out alc882_auto_init_multi_out
12247#define alc262_auto_init_hp_out alc882_auto_init_hp_out
12248#define alc262_auto_init_analog_input alc882_auto_init_analog_input
Takashi Iwaif511b012008-08-15 16:46:42 +020012249#define alc262_auto_init_input_src alc882_auto_init_input_src
Kailang Yangdf694da2005-12-05 19:42:22 +010012250
12251
12252/* init callback for auto-configuration model -- overriding the default init */
Takashi Iwaiae6b8132006-03-03 16:47:17 +010012253static void alc262_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +010012254{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010012255 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010012256 alc262_auto_init_multi_out(codec);
12257 alc262_auto_init_hp_out(codec);
12258 alc262_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020012259 alc262_auto_init_input_src(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +020012260 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010012261 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020012262 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010012263}
12264
12265/*
12266 * configuration and preset
12267 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012268static const char *alc262_models[ALC262_MODEL_LAST] = {
12269 [ALC262_BASIC] = "basic",
12270 [ALC262_HIPPO] = "hippo",
12271 [ALC262_HIPPO_1] = "hippo_1",
12272 [ALC262_FUJITSU] = "fujitsu",
12273 [ALC262_HP_BPC] = "hp-bpc",
Kailang Yangcd7509a2007-01-26 18:33:17 +010012274 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
Takashi Iwai61dc35d2007-11-14 12:26:44 +010012275 [ALC262_HP_TC_T5735] = "hp-tc-t5735",
Kailang Yang8c427222008-01-10 13:03:59 +010012276 [ALC262_HP_RP5700] = "hp-rp5700",
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012277 [ALC262_BENQ_ED8] = "benq",
Takashi Iwai0f405022007-07-06 12:24:11 +020012278 [ALC262_BENQ_T31] = "benq-t31",
12279 [ALC262_SONY_ASSAMD] = "sony-assamd",
Takashi Iwai2922c9a2008-08-27 18:12:42 +020012280 [ALC262_TOSHIBA_S06] = "toshiba-s06",
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012281 [ALC262_TOSHIBA_RX1] = "toshiba-rx1",
Tobin Davisf651b502007-10-26 12:40:47 +020012282 [ALC262_ULTRA] = "ultra",
Jiang zhe0e31daf2008-03-20 12:12:39 +010012283 [ALC262_LENOVO_3000] = "lenovo-3000",
Pascal Terjane8f9ae22008-08-04 14:36:05 +020012284 [ALC262_NEC] = "nec",
Tony Vroonba340e82009-02-02 19:01:30 +000012285 [ALC262_TYAN] = "tyan",
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012286 [ALC262_AUTO] = "auto",
12287};
12288
12289static struct snd_pci_quirk alc262_cfg_tbl[] = {
12290 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
Pascal Terjane8f9ae22008-08-04 14:36:05 +020012291 SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
Takashi Iwaidea0a502009-02-09 17:14:52 +010012292 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
12293 ALC262_HP_BPC),
12294 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
12295 ALC262_HP_BPC),
Takashi Iwai53eff7e2009-02-27 17:49:44 +010012296 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
12297 ALC262_HP_BPC),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012298 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012299 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012300 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012301 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012302 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012303 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012304 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
Kailang Yangcd7509a2007-01-26 18:33:17 +010012305 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012306 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
12307 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
12308 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
Kailang Yang66d2a9d2007-11-14 12:06:21 +010012309 SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
12310 ALC262_HP_TC_T5735),
Kailang Yang8c427222008-01-10 13:03:59 +010012311 SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012312 SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012313 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012314 SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
Takashi Iwaibd6afe32009-03-04 11:30:25 +010012315 SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
Takashi Iwai376b5082009-06-22 11:03:13 +020012316 SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
Daniel T Chen95491d92009-11-08 19:03:55 -050012317 SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
Takashi Iwai12929ba2009-11-17 15:58:35 +010012318 SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
Takashi Iwaic5b51652009-11-17 16:01:58 +010012319#if 0 /* disable the quirk since model=auto works better in recent versions */
Takashi Iwaif872a912009-02-26 00:57:01 +010012320 SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
12321 ALC262_SONY_ASSAMD),
Takashi Iwaic5b51652009-11-17 16:01:58 +010012322#endif
Akio Idehara36ca6e12008-06-09 22:57:40 +090012323 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012324 ALC262_TOSHIBA_RX1),
Kailang Yang80ffe862008-10-15 11:23:27 +020012325 SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012326 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
Tony Vroon3f1eeae2008-02-25 16:44:13 +010012327 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
Tony Vroonba340e82009-02-02 19:01:30 +000012328 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
Takashi Iwaidea0a502009-02-09 17:14:52 +010012329 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
12330 ALC262_ULTRA),
Luke Yelavich3e420e72008-12-16 12:37:47 +110012331 SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
Jiang zhe0e31daf2008-03-20 12:12:39 +010012332 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012333 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
Kailang Yang83c34212007-07-05 11:43:05 +020012334 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010012335 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
Kailang Yangdf694da2005-12-05 19:42:22 +010012336 {}
12337};
12338
12339static struct alc_config_preset alc262_presets[] = {
12340 [ALC262_BASIC] = {
12341 .mixers = { alc262_base_mixer },
12342 .init_verbs = { alc262_init_verbs },
12343 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12344 .dac_nids = alc262_dac_nids,
12345 .hp_nid = 0x03,
12346 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12347 .channel_mode = alc262_modes,
Takashi Iwaia3bcba32005-12-06 19:05:29 +010012348 .input_mux = &alc262_capture_source,
Kailang Yangdf694da2005-12-05 19:42:22 +010012349 },
Kailang Yangccc656c2006-10-17 12:32:26 +020012350 [ALC262_HIPPO] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020012351 .mixers = { alc262_hippo_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +020012352 .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
Kailang Yangccc656c2006-10-17 12:32:26 +020012353 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12354 .dac_nids = alc262_dac_nids,
12355 .hp_nid = 0x03,
12356 .dig_out_nid = ALC262_DIGOUT_NID,
12357 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12358 .channel_mode = alc262_modes,
12359 .input_mux = &alc262_capture_source,
12360 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012361 .setup = alc262_hippo_setup,
12362 .init_hook = alc262_hippo_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +020012363 },
12364 [ALC262_HIPPO_1] = {
12365 .mixers = { alc262_hippo1_mixer },
12366 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
12367 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12368 .dac_nids = alc262_dac_nids,
12369 .hp_nid = 0x02,
12370 .dig_out_nid = ALC262_DIGOUT_NID,
12371 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12372 .channel_mode = alc262_modes,
12373 .input_mux = &alc262_capture_source,
Takashi Iwai42171c12009-05-08 14:11:43 +020012374 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012375 .setup = alc262_hippo1_setup,
12376 .init_hook = alc262_hippo_automute,
Kailang Yangccc656c2006-10-17 12:32:26 +020012377 },
Takashi Iwai834be882006-03-01 14:16:17 +010012378 [ALC262_FUJITSU] = {
12379 .mixers = { alc262_fujitsu_mixer },
Takashi Iwai39d3ed32007-10-12 15:03:48 +020012380 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
12381 alc262_fujitsu_unsol_verbs },
Takashi Iwai834be882006-03-01 14:16:17 +010012382 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12383 .dac_nids = alc262_dac_nids,
12384 .hp_nid = 0x03,
12385 .dig_out_nid = ALC262_DIGOUT_NID,
12386 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12387 .channel_mode = alc262_modes,
12388 .input_mux = &alc262_fujitsu_capture_source,
Takashi Iwaiae6b8132006-03-03 16:47:17 +010012389 .unsol_event = alc262_fujitsu_unsol_event,
Takashi Iwaiebc7a402008-05-20 09:23:05 +020012390 .init_hook = alc262_fujitsu_init_hook,
Takashi Iwai834be882006-03-01 14:16:17 +010012391 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012392 [ALC262_HP_BPC] = {
12393 .mixers = { alc262_HP_BPC_mixer },
12394 .init_verbs = { alc262_HP_BPC_init_verbs },
12395 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12396 .dac_nids = alc262_dac_nids,
12397 .hp_nid = 0x03,
12398 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12399 .channel_mode = alc262_modes,
12400 .input_mux = &alc262_HP_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010012401 .unsol_event = alc262_hp_bpc_unsol_event,
12402 .init_hook = alc262_hp_bpc_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012403 },
Kailang Yangcd7509a2007-01-26 18:33:17 +010012404 [ALC262_HP_BPC_D7000_WF] = {
12405 .mixers = { alc262_HP_BPC_WildWest_mixer },
12406 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
12407 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12408 .dac_nids = alc262_dac_nids,
12409 .hp_nid = 0x03,
12410 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12411 .channel_mode = alc262_modes,
zhejiangaccbe492007-08-31 12:36:05 +020012412 .input_mux = &alc262_HP_D7000_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010012413 .unsol_event = alc262_hp_wildwest_unsol_event,
12414 .init_hook = alc262_hp_wildwest_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012415 },
Kailang Yangcd7509a2007-01-26 18:33:17 +010012416 [ALC262_HP_BPC_D7000_WL] = {
12417 .mixers = { alc262_HP_BPC_WildWest_mixer,
12418 alc262_HP_BPC_WildWest_option_mixer },
12419 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
12420 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12421 .dac_nids = alc262_dac_nids,
12422 .hp_nid = 0x03,
12423 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12424 .channel_mode = alc262_modes,
zhejiangaccbe492007-08-31 12:36:05 +020012425 .input_mux = &alc262_HP_D7000_capture_source,
Takashi Iwaice875f02008-01-28 18:17:43 +010012426 .unsol_event = alc262_hp_wildwest_unsol_event,
12427 .init_hook = alc262_hp_wildwest_automute,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012428 },
Kailang Yang66d2a9d2007-11-14 12:06:21 +010012429 [ALC262_HP_TC_T5735] = {
12430 .mixers = { alc262_hp_t5735_mixer },
12431 .init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
12432 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12433 .dac_nids = alc262_dac_nids,
12434 .hp_nid = 0x03,
12435 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12436 .channel_mode = alc262_modes,
12437 .input_mux = &alc262_capture_source,
Takashi Iwaidc99be42010-01-20 08:35:06 +010012438 .unsol_event = alc_sku_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012439 .setup = alc262_hp_t5735_setup,
Takashi Iwaidc99be42010-01-20 08:35:06 +010012440 .init_hook = alc_inithook,
Kailang Yang8c427222008-01-10 13:03:59 +010012441 },
12442 [ALC262_HP_RP5700] = {
12443 .mixers = { alc262_hp_rp5700_mixer },
12444 .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
12445 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12446 .dac_nids = alc262_dac_nids,
12447 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12448 .channel_mode = alc262_modes,
12449 .input_mux = &alc262_hp_rp5700_capture_source,
Kailang Yang66d2a9d2007-11-14 12:06:21 +010012450 },
Takashi Iwai304dcaa2006-07-25 14:51:16 +020012451 [ALC262_BENQ_ED8] = {
12452 .mixers = { alc262_base_mixer },
12453 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
12454 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12455 .dac_nids = alc262_dac_nids,
12456 .hp_nid = 0x03,
12457 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12458 .channel_mode = alc262_modes,
12459 .input_mux = &alc262_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012460 },
Kailang Yang272a5272007-05-14 11:00:38 +020012461 [ALC262_SONY_ASSAMD] = {
12462 .mixers = { alc262_sony_mixer },
12463 .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
12464 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12465 .dac_nids = alc262_dac_nids,
12466 .hp_nid = 0x02,
12467 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12468 .channel_mode = alc262_modes,
12469 .input_mux = &alc262_capture_source,
12470 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012471 .setup = alc262_hippo_setup,
12472 .init_hook = alc262_hippo_automute,
Kailang Yang83c34212007-07-05 11:43:05 +020012473 },
12474 [ALC262_BENQ_T31] = {
12475 .mixers = { alc262_benq_t31_mixer },
Wu Fengguang6732bd02009-07-30 09:19:14 +020012476 .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
12477 alc_hp15_unsol_verbs },
Kailang Yang83c34212007-07-05 11:43:05 +020012478 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12479 .dac_nids = alc262_dac_nids,
12480 .hp_nid = 0x03,
12481 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12482 .channel_mode = alc262_modes,
12483 .input_mux = &alc262_capture_source,
12484 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012485 .setup = alc262_hippo_setup,
12486 .init_hook = alc262_hippo_automute,
Kailang Yangea1fb292008-08-26 12:58:38 +020012487 },
Tobin Davisf651b502007-10-26 12:40:47 +020012488 [ALC262_ULTRA] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010012489 .mixers = { alc262_ultra_mixer },
12490 .cap_mixer = alc262_ultra_capture_mixer,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010012491 .init_verbs = { alc262_ultra_verbs },
Tobin Davisf651b502007-10-26 12:40:47 +020012492 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12493 .dac_nids = alc262_dac_nids,
Tobin Davisf651b502007-10-26 12:40:47 +020012494 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12495 .channel_mode = alc262_modes,
12496 .input_mux = &alc262_ultra_capture_source,
Takashi Iwaibb9f76c2008-03-12 12:51:09 +010012497 .adc_nids = alc262_adc_nids, /* ADC0 */
12498 .capsrc_nids = alc262_capsrc_nids,
12499 .num_adc_nids = 1, /* single ADC */
Tobin Davisf651b502007-10-26 12:40:47 +020012500 .unsol_event = alc262_ultra_unsol_event,
12501 .init_hook = alc262_ultra_automute,
12502 },
Jiang zhe0e31daf2008-03-20 12:12:39 +010012503 [ALC262_LENOVO_3000] = {
12504 .mixers = { alc262_lenovo_3000_mixer },
12505 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
Daniel T Chene2595322009-12-19 18:19:02 -050012506 alc262_lenovo_3000_unsol_verbs,
12507 alc262_lenovo_3000_init_verbs },
Jiang zhe0e31daf2008-03-20 12:12:39 +010012508 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12509 .dac_nids = alc262_dac_nids,
12510 .hp_nid = 0x03,
12511 .dig_out_nid = ALC262_DIGOUT_NID,
12512 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12513 .channel_mode = alc262_modes,
12514 .input_mux = &alc262_fujitsu_capture_source,
12515 .unsol_event = alc262_lenovo_3000_unsol_event,
12516 },
Pascal Terjane8f9ae22008-08-04 14:36:05 +020012517 [ALC262_NEC] = {
12518 .mixers = { alc262_nec_mixer },
12519 .init_verbs = { alc262_nec_verbs },
12520 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12521 .dac_nids = alc262_dac_nids,
12522 .hp_nid = 0x03,
12523 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12524 .channel_mode = alc262_modes,
12525 .input_mux = &alc262_capture_source,
12526 },
Kailang Yang4e555fe2008-08-26 13:05:55 +020012527 [ALC262_TOSHIBA_S06] = {
12528 .mixers = { alc262_toshiba_s06_mixer },
12529 .init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
12530 alc262_eapd_verbs },
12531 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12532 .capsrc_nids = alc262_dmic_capsrc_nids,
12533 .dac_nids = alc262_dac_nids,
12534 .adc_nids = alc262_dmic_adc_nids, /* ADC0 */
Takashi Iwaiae14ef62009-06-22 08:16:56 +020012535 .num_adc_nids = 1, /* single ADC */
Kailang Yang4e555fe2008-08-26 13:05:55 +020012536 .dig_out_nid = ALC262_DIGOUT_NID,
12537 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12538 .channel_mode = alc262_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012539 .unsol_event = alc_sku_unsol_event,
12540 .setup = alc262_toshiba_s06_setup,
12541 .init_hook = alc_inithook,
Kailang Yang4e555fe2008-08-26 13:05:55 +020012542 },
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012543 [ALC262_TOSHIBA_RX1] = {
12544 .mixers = { alc262_toshiba_rx1_mixer },
12545 .init_verbs = { alc262_init_verbs, alc262_toshiba_rx1_unsol_verbs },
12546 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12547 .dac_nids = alc262_dac_nids,
12548 .hp_nid = 0x03,
12549 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12550 .channel_mode = alc262_modes,
12551 .input_mux = &alc262_capture_source,
12552 .unsol_event = alc262_hippo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012553 .setup = alc262_hippo_setup,
12554 .init_hook = alc262_hippo_automute,
Hiroshi Miura9f99a632008-08-28 16:09:06 +020012555 },
Tony Vroonba340e82009-02-02 19:01:30 +000012556 [ALC262_TYAN] = {
12557 .mixers = { alc262_tyan_mixer },
12558 .init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
12559 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
12560 .dac_nids = alc262_dac_nids,
12561 .hp_nid = 0x02,
12562 .dig_out_nid = ALC262_DIGOUT_NID,
12563 .num_channel_mode = ARRAY_SIZE(alc262_modes),
12564 .channel_mode = alc262_modes,
12565 .input_mux = &alc262_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012566 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012567 .setup = alc262_tyan_setup,
12568 .init_hook = alc_automute_amp,
Tony Vroonba340e82009-02-02 19:01:30 +000012569 },
Kailang Yangdf694da2005-12-05 19:42:22 +010012570};
12571
12572static int patch_alc262(struct hda_codec *codec)
12573{
12574 struct alc_spec *spec;
12575 int board_config;
12576 int err;
12577
Robert P. J. Daydc041e02006-12-19 14:44:15 +010012578 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yangdf694da2005-12-05 19:42:22 +010012579 if (spec == NULL)
12580 return -ENOMEM;
12581
12582 codec->spec = spec;
12583#if 0
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012584 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
12585 * under-run
12586 */
Kailang Yangdf694da2005-12-05 19:42:22 +010012587 {
12588 int tmp;
12589 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
12590 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
12591 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
12592 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
12593 }
12594#endif
Kailang Yangda00c242010-03-19 11:23:45 +010012595 alc_auto_parse_customize_define(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010012596
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +020012597 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
12598
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012599 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
12600 alc262_models,
12601 alc262_cfg_tbl);
Kailang Yangcd7509a2007-01-26 18:33:17 +010012602
Takashi Iwaif5fcc132006-11-24 17:07:44 +010012603 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020012604 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
12605 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +010012606 board_config = ALC262_AUTO;
12607 }
12608
12609 if (board_config == ALC262_AUTO) {
12610 /* automatic parse from the BIOS config */
12611 err = alc262_parse_auto_config(codec);
12612 if (err < 0) {
12613 alc_free(codec);
12614 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012615 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020012616 printk(KERN_INFO
12617 "hda_codec: Cannot set up configuration "
12618 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +010012619 board_config = ALC262_BASIC;
12620 }
12621 }
12622
Takashi Iwaidc1eae22010-07-29 15:30:02 +020012623 if (!spec->no_analog && has_cdefine_beep(codec)) {
Takashi Iwai07eba612009-02-19 08:06:35 +010012624 err = snd_hda_attach_beep_device(codec, 0x1);
12625 if (err < 0) {
12626 alc_free(codec);
12627 return err;
12628 }
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090012629 }
12630
Kailang Yangdf694da2005-12-05 19:42:22 +010012631 if (board_config != ALC262_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020012632 setup_preset(codec, &alc262_presets[board_config]);
Kailang Yangdf694da2005-12-05 19:42:22 +010012633
Kailang Yangdf694da2005-12-05 19:42:22 +010012634 spec->stream_analog_playback = &alc262_pcm_analog_playback;
12635 spec->stream_analog_capture = &alc262_pcm_analog_capture;
Kailang Yangea1fb292008-08-26 12:58:38 +020012636
Kailang Yangdf694da2005-12-05 19:42:22 +010012637 spec->stream_digital_playback = &alc262_pcm_digital_playback;
12638 spec->stream_digital_capture = &alc262_pcm_digital_capture;
12639
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020012640 if (!spec->adc_nids && spec->input_mux) {
Takashi Iwai8c927b42009-06-22 10:56:54 +020012641 int i;
12642 /* check whether the digital-mic has to be supported */
12643 for (i = 0; i < spec->input_mux->num_items; i++) {
12644 if (spec->input_mux->items[i].index >= 9)
12645 break;
12646 }
12647 if (i < spec->input_mux->num_items) {
12648 /* use only ADC0 */
12649 spec->adc_nids = alc262_dmic_adc_nids;
12650 spec->num_adc_nids = 1;
12651 spec->capsrc_nids = alc262_dmic_capsrc_nids;
Kailang Yangdf694da2005-12-05 19:42:22 +010012652 } else {
Takashi Iwai8c927b42009-06-22 10:56:54 +020012653 /* all analog inputs */
12654 /* check whether NID 0x07 is valid */
12655 unsigned int wcap = get_wcaps(codec, 0x07);
12656
12657 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020012658 wcap = get_wcaps_type(wcap);
Takashi Iwai8c927b42009-06-22 10:56:54 +020012659 if (wcap != AC_WID_AUD_IN) {
12660 spec->adc_nids = alc262_adc_nids_alt;
12661 spec->num_adc_nids =
12662 ARRAY_SIZE(alc262_adc_nids_alt);
12663 spec->capsrc_nids = alc262_capsrc_nids_alt;
12664 } else {
12665 spec->adc_nids = alc262_adc_nids;
12666 spec->num_adc_nids =
12667 ARRAY_SIZE(alc262_adc_nids);
12668 spec->capsrc_nids = alc262_capsrc_nids;
12669 }
Kailang Yangdf694da2005-12-05 19:42:22 +010012670 }
12671 }
Takashi Iwaie64f14f2009-01-20 18:32:55 +010012672 if (!spec->cap_mixer && !spec->no_analog)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020012673 set_capture_mixer(codec);
Takashi Iwaidc1eae22010-07-29 15:30:02 +020012674 if (!spec->no_analog && has_cdefine_beep(codec))
Takashi Iwai07eba612009-02-19 08:06:35 +010012675 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Kailang Yangdf694da2005-12-05 19:42:22 +010012676
Takashi Iwai2134ea42008-01-10 16:53:55 +010012677 spec->vmaster_nid = 0x0c;
12678
Kailang Yangdf694da2005-12-05 19:42:22 +010012679 codec->patch_ops = alc_patch_ops;
12680 if (board_config == ALC262_AUTO)
Takashi Iwaiae6b8132006-03-03 16:47:17 +010012681 spec->init_hook = alc262_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020012682#ifdef CONFIG_SND_HDA_POWER_SAVE
12683 if (!spec->loopback.amplist)
12684 spec->loopback.amplist = alc262_loopbacks;
12685#endif
Kailang Yangea1fb292008-08-26 12:58:38 +020012686
Kailang Yangdf694da2005-12-05 19:42:22 +010012687 return 0;
12688}
12689
Kailang Yangdf694da2005-12-05 19:42:22 +010012690/*
Kailang Yanga361d842007-06-05 12:30:55 +020012691 * ALC268 channel source setting (2 channel)
12692 */
12693#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
12694#define alc268_modes alc260_modes
Kailang Yangea1fb292008-08-26 12:58:38 +020012695
Kailang Yanga361d842007-06-05 12:30:55 +020012696static hda_nid_t alc268_dac_nids[2] = {
12697 /* front, hp */
12698 0x02, 0x03
12699};
12700
12701static hda_nid_t alc268_adc_nids[2] = {
12702 /* ADC0-1 */
12703 0x08, 0x07
12704};
12705
12706static hda_nid_t alc268_adc_nids_alt[1] = {
12707 /* ADC0 */
12708 0x08
12709};
12710
Takashi Iwaie1406342008-02-11 18:32:32 +010012711static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
12712
Kailang Yanga361d842007-06-05 12:30:55 +020012713static struct snd_kcontrol_new alc268_base_mixer[] = {
12714 /* output mixer control */
12715 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12716 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12717 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12718 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Takashi Iwai33bf17a2007-08-21 11:51:42 +020012719 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12720 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
12721 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
Kailang Yanga361d842007-06-05 12:30:55 +020012722 { }
12723};
12724
Takashi Iwai42171c12009-05-08 14:11:43 +020012725static struct snd_kcontrol_new alc268_toshiba_mixer[] = {
12726 /* output mixer control */
12727 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12728 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12729 ALC262_HIPPO_MASTER_SWITCH,
12730 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12731 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
12732 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
12733 { }
12734};
12735
Takashi Iwaiaef9d312008-02-19 13:16:41 +010012736/* bind Beep switches of both NID 0x0f and 0x10 */
12737static struct hda_bind_ctls alc268_bind_beep_sw = {
12738 .ops = &snd_hda_bind_sw,
12739 .values = {
12740 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
12741 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
12742 0
12743 },
12744};
12745
12746static struct snd_kcontrol_new alc268_beep_mixer[] = {
12747 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
12748 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
12749 { }
12750};
12751
Kailang Yangd1a991a2007-08-15 16:21:59 +020012752static struct hda_verb alc268_eapd_verbs[] = {
12753 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
12754 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
12755 { }
12756};
12757
Takashi Iwaid2738092007-08-16 14:59:45 +020012758/* Toshiba specific */
Takashi Iwaid2738092007-08-16 14:59:45 +020012759static struct hda_verb alc268_toshiba_verbs[] = {
12760 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12761 { } /* end */
12762};
12763
12764/* Acer specific */
Takashi Iwai889c4392007-08-23 18:56:52 +020012765/* bind volumes of both NID 0x02 and 0x03 */
Takashi Iwai6bc96852007-08-17 09:02:12 +020012766static struct hda_bind_ctls alc268_acer_bind_master_vol = {
12767 .ops = &snd_hda_bind_vol,
12768 .values = {
12769 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
12770 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
12771 0
12772 },
12773};
12774
Takashi Iwai889c4392007-08-23 18:56:52 +020012775/* mute/unmute internal speaker according to the hp jack and mute state */
12776static void alc268_acer_automute(struct hda_codec *codec, int force)
12777{
12778 struct alc_spec *spec = codec->spec;
12779 unsigned int mute;
12780
12781 if (force || !spec->sense_updated) {
Wu Fengguang864f92b2009-11-18 12:38:02 +080012782 spec->jack_present = snd_hda_jack_detect(codec, 0x14);
Takashi Iwai889c4392007-08-23 18:56:52 +020012783 spec->sense_updated = 1;
12784 }
12785 if (spec->jack_present)
12786 mute = HDA_AMP_MUTE; /* mute internal speaker */
12787 else /* unmute internal speaker if necessary */
12788 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
12789 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
12790 HDA_AMP_MUTE, mute);
12791}
12792
12793
12794/* bind hp and internal speaker mute (with plug check) */
12795static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
12796 struct snd_ctl_elem_value *ucontrol)
12797{
12798 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
12799 long *valp = ucontrol->value.integer.value;
12800 int change;
12801
Takashi Iwai8de56b72009-07-24 16:51:47 +020012802 change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
Takashi Iwai889c4392007-08-23 18:56:52 +020012803 if (change)
12804 alc268_acer_automute(codec, 0);
12805 return change;
12806}
Takashi Iwaid2738092007-08-16 14:59:45 +020012807
Kailang Yang8ef355d2008-08-26 13:10:22 +020012808static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
12809 /* output mixer control */
12810 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12811 {
12812 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12813 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012814 .subdevice = HDA_SUBDEV_AMP_FLAG,
Kailang Yang8ef355d2008-08-26 13:10:22 +020012815 .info = snd_hda_mixer_amp_switch_info,
12816 .get = snd_hda_mixer_amp_switch_get,
12817 .put = alc268_acer_master_sw_put,
12818 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12819 },
12820 HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
12821 { }
12822};
12823
Takashi Iwaid2738092007-08-16 14:59:45 +020012824static struct snd_kcontrol_new alc268_acer_mixer[] = {
12825 /* output mixer control */
12826 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12827 {
12828 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12829 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012830 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwaid2738092007-08-16 14:59:45 +020012831 .info = snd_hda_mixer_amp_switch_info,
12832 .get = snd_hda_mixer_amp_switch_get,
12833 .put = alc268_acer_master_sw_put,
12834 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12835 },
Takashi Iwai33bf17a2007-08-21 11:51:42 +020012836 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12837 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
12838 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
Takashi Iwaid2738092007-08-16 14:59:45 +020012839 { }
12840};
12841
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012842static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
12843 /* output mixer control */
12844 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
12845 {
12846 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
12847 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010012848 .subdevice = HDA_SUBDEV_AMP_FLAG,
Takashi Iwaic238b4f2008-11-05 14:57:20 +010012849 .info = snd_hda_mixer_amp_switch_info,
12850 .get = snd_hda_mixer_amp_switch_get,
12851 .put = alc268_acer_master_sw_put,
12852 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
12853 },
12854 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12855 HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
12856 { }
12857};
12858
Kailang Yang8ef355d2008-08-26 13:10:22 +020012859static struct hda_verb alc268_acer_aspire_one_verbs[] = {
12860 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
12861 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12862 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12863 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
12864 {0x23, AC_VERB_SET_CONNECT_SEL, 0x06},
12865 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, 0xa017},
12866 { }
12867};
12868
Takashi Iwaid2738092007-08-16 14:59:45 +020012869static struct hda_verb alc268_acer_verbs[] = {
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012870 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
12871 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Takashi Iwaid2738092007-08-16 14:59:45 +020012872 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12873 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
Takashi Iwai0ccb5412008-03-06 16:58:35 +010012874 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
12875 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
Takashi Iwaid2738092007-08-16 14:59:45 +020012876 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12877 { }
12878};
12879
12880/* unsolicited event for HP jack sensing */
Takashi Iwai42171c12009-05-08 14:11:43 +020012881#define alc268_toshiba_unsol_event alc262_hippo_unsol_event
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012882#define alc268_toshiba_setup alc262_hippo_setup
12883#define alc268_toshiba_automute alc262_hippo_automute
Takashi Iwaid2738092007-08-16 14:59:45 +020012884
12885static void alc268_acer_unsol_event(struct hda_codec *codec,
12886 unsigned int res)
12887{
Takashi Iwai889c4392007-08-23 18:56:52 +020012888 if ((res >> 26) != ALC880_HP_EVENT)
Takashi Iwaid2738092007-08-16 14:59:45 +020012889 return;
12890 alc268_acer_automute(codec, 1);
12891}
12892
Takashi Iwai889c4392007-08-23 18:56:52 +020012893static void alc268_acer_init_hook(struct hda_codec *codec)
12894{
12895 alc268_acer_automute(codec, 1);
12896}
12897
Kailang Yang8ef355d2008-08-26 13:10:22 +020012898/* toggle speaker-output according to the hp-jack state */
12899static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
12900{
12901 unsigned int present;
12902 unsigned char bits;
12903
Wu Fengguang864f92b2009-11-18 12:38:02 +080012904 present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020012905 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yang8ef355d2008-08-26 13:10:22 +020012906 snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020012907 HDA_AMP_MUTE, bits);
Kailang Yang8ef355d2008-08-26 13:10:22 +020012908 snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020012909 HDA_AMP_MUTE, bits);
Kailang Yang8ef355d2008-08-26 13:10:22 +020012910}
12911
Kailang Yang8ef355d2008-08-26 13:10:22 +020012912static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
12913 unsigned int res)
12914{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012915 switch (res >> 26) {
12916 case ALC880_HP_EVENT:
Kailang Yang8ef355d2008-08-26 13:10:22 +020012917 alc268_aspire_one_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012918 break;
12919 case ALC880_MIC_EVENT:
12920 alc_mic_automute(codec);
12921 break;
12922 }
12923}
12924
12925static void alc268_acer_lc_setup(struct hda_codec *codec)
12926{
12927 struct alc_spec *spec = codec->spec;
12928 spec->ext_mic.pin = 0x18;
12929 spec->ext_mic.mux_idx = 0;
12930 spec->int_mic.pin = 0x12;
12931 spec->int_mic.mux_idx = 6;
12932 spec->auto_mic = 1;
Kailang Yang8ef355d2008-08-26 13:10:22 +020012933}
12934
12935static void alc268_acer_lc_init_hook(struct hda_codec *codec)
12936{
12937 alc268_aspire_one_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012938 alc_mic_automute(codec);
Kailang Yang8ef355d2008-08-26 13:10:22 +020012939}
12940
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012941static struct snd_kcontrol_new alc268_dell_mixer[] = {
12942 /* output mixer control */
12943 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
12944 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12945 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
12946 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
12947 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
12948 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
12949 { }
12950};
12951
12952static struct hda_verb alc268_dell_verbs[] = {
12953 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12954 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
12955 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012956 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012957 { }
12958};
12959
12960/* mute/unmute internal speaker according to the hp jack and mute state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012961static void alc268_dell_setup(struct hda_codec *codec)
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012962{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012963 struct alc_spec *spec = codec->spec;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012964
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012965 spec->autocfg.hp_pins[0] = 0x15;
12966 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012967 spec->ext_mic.pin = 0x18;
12968 spec->ext_mic.mux_idx = 0;
12969 spec->int_mic.pin = 0x19;
12970 spec->int_mic.mux_idx = 1;
12971 spec->auto_mic = 1;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010012972}
12973
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012974static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
12975 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
12976 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
12977 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
12978 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
12979 HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
12980 HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
12981 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
12982 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
12983 { }
12984};
12985
12986static struct hda_verb alc267_quanta_il1_verbs[] = {
12987 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
12988 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
12989 { }
12990};
12991
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012992static void alc267_quanta_il1_setup(struct hda_codec *codec)
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020012993{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012994 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020012995 spec->autocfg.hp_pins[0] = 0x15;
12996 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020012997 spec->ext_mic.pin = 0x18;
12998 spec->ext_mic.mux_idx = 0;
12999 spec->int_mic.pin = 0x19;
13000 spec->int_mic.mux_idx = 1;
13001 spec->auto_mic = 1;
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013002}
13003
Kailang Yanga361d842007-06-05 12:30:55 +020013004/*
13005 * generic initialization of ADC, input mixers and output mixers
13006 */
13007static struct hda_verb alc268_base_init_verbs[] = {
13008 /* Unmute DAC0-1 and set vol = 0 */
13009 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020013010 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020013011
13012 /*
13013 * Set up output mixers (0x0c - 0x0e)
13014 */
13015 /* set vol=0 to output mixers */
13016 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yanga361d842007-06-05 12:30:55 +020013017 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
13018
13019 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13020 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13021
13022 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
13023 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
13024 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
13025 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13026 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13027 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13028 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13029 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13030
13031 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13032 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13033 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
13034 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020013035 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013036
13037 /* set PCBEEP vol = 0, mute connections */
13038 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13039 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13040 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yanga361d842007-06-05 12:30:55 +020013041
Jiang Zhea9b3aa82007-12-20 13:13:13 +010013042 /* Unmute Selector 23h,24h and set the default input to mic-in */
Kailang Yangea1fb292008-08-26 12:58:38 +020013043
Jiang Zhea9b3aa82007-12-20 13:13:13 +010013044 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
13045 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13046 {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
13047 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020013048
Kailang Yanga361d842007-06-05 12:30:55 +020013049 { }
13050};
13051
13052/*
13053 * generic initialization of ADC, input mixers and output mixers
13054 */
13055static struct hda_verb alc268_volume_init_verbs[] = {
13056 /* set output DAC */
Takashi Iwai4cfb91c2009-01-23 12:53:09 +010013057 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
13058 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
Kailang Yanga361d842007-06-05 12:30:55 +020013059
13060 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13061 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
13062 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13063 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13064 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
13065
Kailang Yanga361d842007-06-05 12:30:55 +020013066 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yanga361d842007-06-05 12:30:55 +020013067 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13068 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13069
13070 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020013071 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yanga361d842007-06-05 12:30:55 +020013072
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013073 /* set PCBEEP vol = 0, mute connections */
13074 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
13075 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
13076 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yanga361d842007-06-05 12:30:55 +020013077
13078 { }
13079};
13080
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013081static struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
13082 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13083 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
13084 { } /* end */
13085};
13086
Kailang Yanga361d842007-06-05 12:30:55 +020013087static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
13088 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13089 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013090 _DEFINE_CAPSRC(1),
Kailang Yanga361d842007-06-05 12:30:55 +020013091 { } /* end */
13092};
13093
13094static struct snd_kcontrol_new alc268_capture_mixer[] = {
13095 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13096 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
13097 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
13098 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013099 _DEFINE_CAPSRC(2),
Kailang Yanga361d842007-06-05 12:30:55 +020013100 { } /* end */
13101};
13102
13103static struct hda_input_mux alc268_capture_source = {
13104 .num_items = 4,
13105 .items = {
13106 { "Mic", 0x0 },
13107 { "Front Mic", 0x1 },
13108 { "Line", 0x2 },
13109 { "CD", 0x3 },
13110 },
13111};
13112
Takashi Iwai0ccb5412008-03-06 16:58:35 +010013113static struct hda_input_mux alc268_acer_capture_source = {
13114 .num_items = 3,
13115 .items = {
13116 { "Mic", 0x0 },
Takashi Iwaic238b4f2008-11-05 14:57:20 +010013117 { "Internal Mic", 0x1 },
13118 { "Line", 0x2 },
13119 },
13120};
13121
13122static struct hda_input_mux alc268_acer_dmic_capture_source = {
13123 .num_items = 3,
13124 .items = {
13125 { "Mic", 0x0 },
Takashi Iwai0ccb5412008-03-06 16:58:35 +010013126 { "Internal Mic", 0x6 },
13127 { "Line", 0x2 },
13128 },
13129};
13130
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013131#ifdef CONFIG_SND_DEBUG
13132static struct snd_kcontrol_new alc268_test_mixer[] = {
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013133 /* Volume widgets */
13134 HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13135 HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13136 HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
13137 HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
13138 HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
13139 HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
13140 HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
13141 HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
13142 HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
13143 HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
13144 HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
13145 HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
13146 HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
Takashi Iwaif0747ee2008-01-15 11:41:41 +010013147 /* The below appears problematic on some hardwares */
13148 /*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013149 HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
13150 HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
13151 HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
13152 HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
13153
13154 /* Modes for retasking pin widgets */
13155 ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
13156 ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
13157 ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
13158 ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
13159
13160 /* Controls for GPIO pins, assuming they are configured as outputs */
13161 ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
13162 ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
13163 ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
13164 ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
13165
13166 /* Switches to allow the digital SPDIF output pin to be enabled.
13167 * The ALC268 does not have an SPDIF input.
13168 */
13169 ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
13170
13171 /* A switch allowing EAPD to be enabled. Some laptops seem to use
13172 * this output to turn on an external amplifier.
13173 */
13174 ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
13175 ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
13176
13177 { } /* end */
13178};
13179#endif
13180
Kailang Yanga361d842007-06-05 12:30:55 +020013181/* create input playback/capture controls for the given pin */
13182static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
13183 const char *ctlname, int idx)
13184{
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013185 hda_nid_t dac;
Kailang Yanga361d842007-06-05 12:30:55 +020013186 int err;
13187
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013188 switch (nid) {
13189 case 0x14:
13190 case 0x16:
13191 dac = 0x02;
13192 break;
13193 case 0x15:
Takashi Iwaib08b1632010-07-30 14:08:25 +020013194 case 0x1a: /* ALC259/269 only */
13195 case 0x1b: /* ALC259/269 only */
Kailang Yang531d8792010-04-09 10:57:33 +020013196 case 0x21: /* ALC269vb has this pin, too */
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013197 dac = 0x03;
13198 break;
13199 default:
Takashi Iwaic7a94342010-07-30 14:10:43 +020013200 snd_printd(KERN_WARNING "hda_codec: "
13201 "ignoring pin 0x%x as unknown\n", nid);
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013202 return 0;
13203 }
13204 if (spec->multiout.dac_nids[0] != dac &&
13205 spec->multiout.dac_nids[1] != dac) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020013206 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013207 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
Kailang Yanga361d842007-06-05 12:30:55 +020013208 HDA_OUTPUT));
13209 if (err < 0)
13210 return err;
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013211 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
13212 }
13213
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013214 if (nid != 0x16)
Takashi Iwai0afe5f82009-10-02 09:20:00 +020013215 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
Kailang Yanga361d842007-06-05 12:30:55 +020013216 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013217 else /* mono */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020013218 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013219 HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
Kailang Yanga361d842007-06-05 12:30:55 +020013220 if (err < 0)
13221 return err;
13222 return 0;
13223}
13224
13225/* add playback controls from the parsed DAC table */
13226static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
13227 const struct auto_pin_cfg *cfg)
13228{
13229 hda_nid_t nid;
13230 int err;
13231
Kailang Yanga361d842007-06-05 12:30:55 +020013232 spec->multiout.dac_nids = spec->private_dac_nids;
Kailang Yanga361d842007-06-05 12:30:55 +020013233
13234 nid = cfg->line_out_pins[0];
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013235 if (nid) {
13236 const char *name;
13237 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
13238 name = "Speaker";
13239 else
13240 name = "Front";
13241 err = alc268_new_analog_output(spec, nid, name, 0);
13242 if (err < 0)
13243 return err;
13244 }
Kailang Yanga361d842007-06-05 12:30:55 +020013245
13246 nid = cfg->speaker_pins[0];
13247 if (nid == 0x1d) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020013248 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
Kailang Yanga361d842007-06-05 12:30:55 +020013249 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
13250 if (err < 0)
13251 return err;
David Henningsson7bfb9c02010-08-02 13:13:25 +020013252 } else if (nid) {
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013253 err = alc268_new_analog_output(spec, nid, "Speaker", 0);
13254 if (err < 0)
13255 return err;
Kailang Yanga361d842007-06-05 12:30:55 +020013256 }
13257 nid = cfg->hp_pins[0];
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013258 if (nid) {
13259 err = alc268_new_analog_output(spec, nid, "Headphone", 0);
13260 if (err < 0)
13261 return err;
13262 }
Kailang Yanga361d842007-06-05 12:30:55 +020013263
13264 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
13265 if (nid == 0x16) {
Takashi Iwai0afe5f82009-10-02 09:20:00 +020013266 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
Takashi Iwai3f3b7c12009-07-17 14:36:59 +020013267 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
Kailang Yanga361d842007-06-05 12:30:55 +020013268 if (err < 0)
13269 return err;
13270 }
Kailang Yangea1fb292008-08-26 12:58:38 +020013271 return 0;
Kailang Yanga361d842007-06-05 12:30:55 +020013272}
13273
13274/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020013275static int alc268_auto_create_input_ctls(struct hda_codec *codec,
Kailang Yanga361d842007-06-05 12:30:55 +020013276 const struct auto_pin_cfg *cfg)
13277{
Takashi Iwai05f5f472009-08-25 13:10:18 +020013278 return alc_auto_create_input_ctls(codec, cfg, 0, 0x23, 0x24);
Kailang Yanga361d842007-06-05 12:30:55 +020013279}
13280
Takashi Iwaie9af4f32009-08-29 23:23:08 +020013281static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
13282 hda_nid_t nid, int pin_type)
13283{
13284 int idx;
13285
13286 alc_set_pin_output(codec, nid, pin_type);
13287 if (nid == 0x14 || nid == 0x16)
13288 idx = 0;
13289 else
13290 idx = 1;
13291 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
13292}
13293
13294static void alc268_auto_init_multi_out(struct hda_codec *codec)
13295{
13296 struct alc_spec *spec = codec->spec;
13297 hda_nid_t nid = spec->autocfg.line_out_pins[0];
13298 if (nid) {
13299 int pin_type = get_pin_type(spec->autocfg.line_out_type);
13300 alc268_auto_set_output_and_unmute(codec, nid, pin_type);
13301 }
13302}
13303
13304static void alc268_auto_init_hp_out(struct hda_codec *codec)
13305{
13306 struct alc_spec *spec = codec->spec;
13307 hda_nid_t pin;
13308
13309 pin = spec->autocfg.hp_pins[0];
13310 if (pin)
13311 alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
13312 pin = spec->autocfg.speaker_pins[0];
13313 if (pin)
13314 alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
13315}
13316
Kailang Yanga361d842007-06-05 12:30:55 +020013317static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
13318{
13319 struct alc_spec *spec = codec->spec;
13320 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
13321 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
13322 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
13323 unsigned int dac_vol1, dac_vol2;
13324
Takashi Iwaie9af4f32009-08-29 23:23:08 +020013325 if (line_nid == 0x1d || speaker_nid == 0x1d) {
Kailang Yanga361d842007-06-05 12:30:55 +020013326 snd_hda_codec_write(codec, speaker_nid, 0,
13327 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
Takashi Iwaie9af4f32009-08-29 23:23:08 +020013328 /* mute mixer inputs from 0x1d */
Kailang Yanga361d842007-06-05 12:30:55 +020013329 snd_hda_codec_write(codec, 0x0f, 0,
13330 AC_VERB_SET_AMP_GAIN_MUTE,
13331 AMP_IN_UNMUTE(1));
13332 snd_hda_codec_write(codec, 0x10, 0,
13333 AC_VERB_SET_AMP_GAIN_MUTE,
13334 AMP_IN_UNMUTE(1));
13335 } else {
Takashi Iwaie9af4f32009-08-29 23:23:08 +020013336 /* unmute mixer inputs from 0x1d */
Kailang Yanga361d842007-06-05 12:30:55 +020013337 snd_hda_codec_write(codec, 0x0f, 0,
13338 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
13339 snd_hda_codec_write(codec, 0x10, 0,
13340 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
13341 }
13342
13343 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */
Kailang Yangea1fb292008-08-26 12:58:38 +020013344 if (line_nid == 0x14)
Kailang Yanga361d842007-06-05 12:30:55 +020013345 dac_vol2 = AMP_OUT_ZERO;
13346 else if (line_nid == 0x15)
13347 dac_vol1 = AMP_OUT_ZERO;
Kailang Yangea1fb292008-08-26 12:58:38 +020013348 if (hp_nid == 0x14)
Kailang Yanga361d842007-06-05 12:30:55 +020013349 dac_vol2 = AMP_OUT_ZERO;
13350 else if (hp_nid == 0x15)
13351 dac_vol1 = AMP_OUT_ZERO;
13352 if (line_nid != 0x16 || hp_nid != 0x16 ||
13353 spec->autocfg.line_out_pins[1] != 0x16 ||
13354 spec->autocfg.line_out_pins[2] != 0x16)
13355 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
13356
13357 snd_hda_codec_write(codec, 0x02, 0,
13358 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
13359 snd_hda_codec_write(codec, 0x03, 0,
13360 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
13361}
13362
Sasha Alexandrdef319f2009-06-16 16:00:15 -040013363/* pcm configuration: identical with ALC880 */
Kailang Yanga361d842007-06-05 12:30:55 +020013364#define alc268_pcm_analog_playback alc880_pcm_analog_playback
13365#define alc268_pcm_analog_capture alc880_pcm_analog_capture
Takashi Iwai63300792008-01-24 15:31:36 +010013366#define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
Kailang Yanga361d842007-06-05 12:30:55 +020013367#define alc268_pcm_digital_playback alc880_pcm_digital_playback
13368
13369/*
13370 * BIOS auto configuration
13371 */
13372static int alc268_parse_auto_config(struct hda_codec *codec)
13373{
13374 struct alc_spec *spec = codec->spec;
13375 int err;
13376 static hda_nid_t alc268_ignore[] = { 0 };
13377
13378 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
13379 alc268_ignore);
13380 if (err < 0)
13381 return err;
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013382 if (!spec->autocfg.line_outs) {
13383 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
13384 spec->multiout.max_channels = 2;
13385 spec->no_analog = 1;
13386 goto dig_only;
13387 }
Kailang Yanga361d842007-06-05 12:30:55 +020013388 return 0; /* can't find valid BIOS pin config */
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013389 }
Kailang Yanga361d842007-06-05 12:30:55 +020013390 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
13391 if (err < 0)
13392 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020013393 err = alc268_auto_create_input_ctls(codec, &spec->autocfg);
Kailang Yanga361d842007-06-05 12:30:55 +020013394 if (err < 0)
13395 return err;
13396
13397 spec->multiout.max_channels = 2;
13398
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013399 dig_only:
Kailang Yanga361d842007-06-05 12:30:55 +020013400 /* digital only support output */
Takashi Iwai757899a2010-07-30 10:48:14 +020013401 alc_auto_parse_digital(codec);
Takashi Iwai603c4012008-07-30 15:01:44 +020013402 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010013403 add_mixer(spec, spec->kctls.list);
Kailang Yanga361d842007-06-05 12:30:55 +020013404
Takashi Iwai892981f2009-03-02 08:04:35 +010013405 if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d)
Takashi Iwaid88897e2008-10-31 15:01:37 +010013406 add_mixer(spec, alc268_beep_mixer);
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013407
Takashi Iwaid88897e2008-10-31 15:01:37 +010013408 add_verb(spec, alc268_volume_init_verbs);
Herton Ronaldo Krzesinski59085892009-08-11 22:33:09 -030013409 spec->num_mux_defs = 2;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020013410 spec->input_mux = &spec->private_imux[0];
Kailang Yanga361d842007-06-05 12:30:55 +020013411
Takashi Iwai776e1842007-08-29 15:07:11 +020013412 err = alc_auto_add_mic_boost(codec);
13413 if (err < 0)
13414 return err;
13415
Kailang Yang6227cdc2010-02-25 08:36:52 +010013416 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai1d955eb2009-06-29 11:33:53 +020013417
Kailang Yanga361d842007-06-05 12:30:55 +020013418 return 1;
13419}
13420
Kailang Yanga361d842007-06-05 12:30:55 +020013421#define alc268_auto_init_analog_input alc882_auto_init_analog_input
13422
13423/* init callback for auto-configuration model -- overriding the default init */
13424static void alc268_auto_init(struct hda_codec *codec)
13425{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010013426 struct alc_spec *spec = codec->spec;
Kailang Yanga361d842007-06-05 12:30:55 +020013427 alc268_auto_init_multi_out(codec);
13428 alc268_auto_init_hp_out(codec);
13429 alc268_auto_init_mono_speaker_out(codec);
13430 alc268_auto_init_analog_input(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +020013431 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010013432 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020013433 alc_inithook(codec);
Kailang Yanga361d842007-06-05 12:30:55 +020013434}
13435
13436/*
13437 * configuration and preset
13438 */
13439static const char *alc268_models[ALC268_MODEL_LAST] = {
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013440 [ALC267_QUANTA_IL1] = "quanta-il1",
Kailang Yanga361d842007-06-05 12:30:55 +020013441 [ALC268_3ST] = "3stack",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020013442 [ALC268_TOSHIBA] = "toshiba",
Takashi Iwaid2738092007-08-16 14:59:45 +020013443 [ALC268_ACER] = "acer",
Takashi Iwaic238b4f2008-11-05 14:57:20 +010013444 [ALC268_ACER_DMIC] = "acer-dmic",
Kailang Yang8ef355d2008-08-26 13:10:22 +020013445 [ALC268_ACER_ASPIRE_ONE] = "acer-aspire",
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013446 [ALC268_DELL] = "dell",
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013447 [ALC268_ZEPTO] = "zepto",
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013448#ifdef CONFIG_SND_DEBUG
13449 [ALC268_TEST] = "test",
13450#endif
Kailang Yanga361d842007-06-05 12:30:55 +020013451 [ALC268_AUTO] = "auto",
13452};
13453
13454static struct snd_pci_quirk alc268_cfg_tbl[] = {
Takashi Iwaia0b8f7d2008-04-22 19:39:49 +020013455 SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010013456 SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
Andy Shevchenkodafc8352008-01-25 11:53:50 +010013457 SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010013458 SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
Andy Shevchenko29a52c22008-01-24 17:29:00 +010013459 SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
Kailang Yang8ef355d2008-08-26 13:10:22 +020013460 SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
13461 ALC268_ACER_ASPIRE_ONE),
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013462 SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
Daniel T Chena1bf8082009-11-01 18:32:29 -050013463 SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
13464 "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
Takashi Iwai33d78672009-09-08 11:03:41 +020013465 /* almost compatible with toshiba but with optional digital outs;
13466 * auto-probing seems working fine
13467 */
Takashi Iwai8871e5b2009-06-02 01:02:50 +020013468 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP TX25xx series",
Takashi Iwai33d78672009-09-08 11:03:41 +020013469 ALC268_AUTO),
Kailang Yanga361d842007-06-05 12:30:55 +020013470 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
Takashi Iwai8871e5b2009-06-02 01:02:50 +020013471 SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
Tony Vroon378bd6a2008-06-04 12:08:30 +020013472 SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
Takashi Iwaib875bf32007-09-06 15:00:27 +020013473 SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013474 SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
Kailang Yanga361d842007-06-05 12:30:55 +020013475 {}
13476};
13477
Takashi Iwai3abf2f32009-08-19 20:05:02 +020013478/* Toshiba laptops have no unique PCI SSID but only codec SSID */
13479static struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
13480 SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
13481 SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
13482 SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
13483 ALC268_TOSHIBA),
13484 {}
13485};
13486
Kailang Yanga361d842007-06-05 12:30:55 +020013487static struct alc_config_preset alc268_presets[] = {
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013488 [ALC267_QUANTA_IL1] = {
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013489 .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
13490 alc268_capture_nosrc_mixer },
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013491 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13492 alc267_quanta_il1_verbs },
13493 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13494 .dac_nids = alc268_dac_nids,
13495 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13496 .adc_nids = alc268_adc_nids_alt,
13497 .hp_nid = 0x03,
13498 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13499 .channel_mode = alc268_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013500 .unsol_event = alc_sku_unsol_event,
13501 .setup = alc267_quanta_il1_setup,
13502 .init_hook = alc_inithook,
Herton Ronaldo Krzesinskieb5a6622008-04-14 13:46:28 +020013503 },
Kailang Yanga361d842007-06-05 12:30:55 +020013504 [ALC268_3ST] = {
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013505 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
13506 alc268_beep_mixer },
Kailang Yanga361d842007-06-05 12:30:55 +020013507 .init_verbs = { alc268_base_init_verbs },
13508 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13509 .dac_nids = alc268_dac_nids,
13510 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13511 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013512 .capsrc_nids = alc268_capsrc_nids,
Kailang Yanga361d842007-06-05 12:30:55 +020013513 .hp_nid = 0x03,
13514 .dig_out_nid = ALC268_DIGOUT_NID,
13515 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13516 .channel_mode = alc268_modes,
13517 .input_mux = &alc268_capture_source,
13518 },
Kailang Yangd1a991a2007-08-15 16:21:59 +020013519 [ALC268_TOSHIBA] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020013520 .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013521 alc268_beep_mixer },
Takashi Iwaid2738092007-08-16 14:59:45 +020013522 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13523 alc268_toshiba_verbs },
Kailang Yangd1a991a2007-08-15 16:21:59 +020013524 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13525 .dac_nids = alc268_dac_nids,
13526 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13527 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013528 .capsrc_nids = alc268_capsrc_nids,
Kailang Yangd1a991a2007-08-15 16:21:59 +020013529 .hp_nid = 0x03,
13530 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13531 .channel_mode = alc268_modes,
13532 .input_mux = &alc268_capture_source,
Takashi Iwaid2738092007-08-16 14:59:45 +020013533 .unsol_event = alc268_toshiba_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013534 .setup = alc268_toshiba_setup,
13535 .init_hook = alc268_toshiba_automute,
Takashi Iwaid2738092007-08-16 14:59:45 +020013536 },
13537 [ALC268_ACER] = {
Takashi Iwai432fd132009-09-30 08:13:44 +020013538 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013539 alc268_beep_mixer },
Takashi Iwaid2738092007-08-16 14:59:45 +020013540 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13541 alc268_acer_verbs },
13542 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13543 .dac_nids = alc268_dac_nids,
13544 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13545 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013546 .capsrc_nids = alc268_capsrc_nids,
Takashi Iwaid2738092007-08-16 14:59:45 +020013547 .hp_nid = 0x02,
13548 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13549 .channel_mode = alc268_modes,
Takashi Iwai0ccb5412008-03-06 16:58:35 +010013550 .input_mux = &alc268_acer_capture_source,
Takashi Iwaid2738092007-08-16 14:59:45 +020013551 .unsol_event = alc268_acer_unsol_event,
Takashi Iwai889c4392007-08-23 18:56:52 +020013552 .init_hook = alc268_acer_init_hook,
Kailang Yangd1a991a2007-08-15 16:21:59 +020013553 },
Takashi Iwaic238b4f2008-11-05 14:57:20 +010013554 [ALC268_ACER_DMIC] = {
13555 .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
13556 alc268_beep_mixer },
13557 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13558 alc268_acer_verbs },
13559 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13560 .dac_nids = alc268_dac_nids,
13561 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13562 .adc_nids = alc268_adc_nids_alt,
13563 .capsrc_nids = alc268_capsrc_nids,
13564 .hp_nid = 0x02,
13565 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13566 .channel_mode = alc268_modes,
13567 .input_mux = &alc268_acer_dmic_capture_source,
13568 .unsol_event = alc268_acer_unsol_event,
13569 .init_hook = alc268_acer_init_hook,
13570 },
Kailang Yang8ef355d2008-08-26 13:10:22 +020013571 [ALC268_ACER_ASPIRE_ONE] = {
13572 .mixers = { alc268_acer_aspire_one_mixer,
Takashi Iwai22971e32009-02-10 11:56:44 +010013573 alc268_beep_mixer,
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013574 alc268_capture_nosrc_mixer },
Kailang Yang8ef355d2008-08-26 13:10:22 +020013575 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13576 alc268_acer_aspire_one_verbs },
13577 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13578 .dac_nids = alc268_dac_nids,
13579 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13580 .adc_nids = alc268_adc_nids_alt,
13581 .capsrc_nids = alc268_capsrc_nids,
13582 .hp_nid = 0x03,
13583 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13584 .channel_mode = alc268_modes,
Kailang Yang8ef355d2008-08-26 13:10:22 +020013585 .unsol_event = alc268_acer_lc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013586 .setup = alc268_acer_lc_setup,
Kailang Yang8ef355d2008-08-26 13:10:22 +020013587 .init_hook = alc268_acer_lc_init_hook,
13588 },
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013589 [ALC268_DELL] = {
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013590 .mixers = { alc268_dell_mixer, alc268_beep_mixer,
13591 alc268_capture_nosrc_mixer },
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013592 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13593 alc268_dell_verbs },
13594 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13595 .dac_nids = alc268_dac_nids,
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013596 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13597 .adc_nids = alc268_adc_nids_alt,
13598 .capsrc_nids = alc268_capsrc_nids,
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013599 .hp_nid = 0x02,
13600 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13601 .channel_mode = alc268_modes,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020013602 .unsol_event = alc_sku_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013603 .setup = alc268_dell_setup,
13604 .init_hook = alc_inithook,
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013605 },
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013606 [ALC268_ZEPTO] = {
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013607 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
13608 alc268_beep_mixer },
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013609 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13610 alc268_toshiba_verbs },
13611 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13612 .dac_nids = alc268_dac_nids,
13613 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13614 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013615 .capsrc_nids = alc268_capsrc_nids,
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013616 .hp_nid = 0x03,
13617 .dig_out_nid = ALC268_DIGOUT_NID,
13618 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13619 .channel_mode = alc268_modes,
13620 .input_mux = &alc268_capture_source,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020013621 .setup = alc268_toshiba_setup,
13622 .init_hook = alc268_toshiba_automute,
Mirco Tischlerf12462c2008-02-04 12:33:59 +010013623 },
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013624#ifdef CONFIG_SND_DEBUG
13625 [ALC268_TEST] = {
13626 .mixers = { alc268_test_mixer, alc268_capture_mixer },
13627 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
13628 alc268_volume_init_verbs },
13629 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
13630 .dac_nids = alc268_dac_nids,
13631 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
13632 .adc_nids = alc268_adc_nids_alt,
Takashi Iwaie1406342008-02-11 18:32:32 +010013633 .capsrc_nids = alc268_capsrc_nids,
Jonathan Woithe86c53bd2008-01-08 12:33:19 +010013634 .hp_nid = 0x03,
13635 .dig_out_nid = ALC268_DIGOUT_NID,
13636 .num_channel_mode = ARRAY_SIZE(alc268_modes),
13637 .channel_mode = alc268_modes,
13638 .input_mux = &alc268_capture_source,
13639 },
13640#endif
Kailang Yanga361d842007-06-05 12:30:55 +020013641};
13642
13643static int patch_alc268(struct hda_codec *codec)
13644{
13645 struct alc_spec *spec;
13646 int board_config;
Takashi Iwai22971e32009-02-10 11:56:44 +010013647 int i, has_beep, err;
Kailang Yanga361d842007-06-05 12:30:55 +020013648
Julia Lawallef86f582009-12-19 08:18:03 +010013649 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yanga361d842007-06-05 12:30:55 +020013650 if (spec == NULL)
13651 return -ENOMEM;
13652
13653 codec->spec = spec;
13654
13655 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
13656 alc268_models,
13657 alc268_cfg_tbl);
13658
Takashi Iwai3abf2f32009-08-19 20:05:02 +020013659 if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
13660 board_config = snd_hda_check_board_codec_sid_config(codec,
Takashi Iwai50ae0aa2010-03-08 12:09:59 +010013661 ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
Takashi Iwai3abf2f32009-08-19 20:05:02 +020013662
Kailang Yanga361d842007-06-05 12:30:55 +020013663 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020013664 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
13665 codec->chip_name);
Kailang Yanga361d842007-06-05 12:30:55 +020013666 board_config = ALC268_AUTO;
13667 }
13668
13669 if (board_config == ALC268_AUTO) {
13670 /* automatic parse from the BIOS config */
13671 err = alc268_parse_auto_config(codec);
13672 if (err < 0) {
13673 alc_free(codec);
13674 return err;
13675 } else if (!err) {
13676 printk(KERN_INFO
13677 "hda_codec: Cannot set up configuration "
13678 "from BIOS. Using base mode...\n");
13679 board_config = ALC268_3ST;
13680 }
13681 }
13682
13683 if (board_config != ALC268_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020013684 setup_preset(codec, &alc268_presets[board_config]);
Kailang Yanga361d842007-06-05 12:30:55 +020013685
Kailang Yanga361d842007-06-05 12:30:55 +020013686 spec->stream_analog_playback = &alc268_pcm_analog_playback;
13687 spec->stream_analog_capture = &alc268_pcm_analog_capture;
Takashi Iwai63300792008-01-24 15:31:36 +010013688 spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
Kailang Yanga361d842007-06-05 12:30:55 +020013689
Kailang Yanga361d842007-06-05 12:30:55 +020013690 spec->stream_digital_playback = &alc268_pcm_digital_playback;
13691
Takashi Iwai22971e32009-02-10 11:56:44 +010013692 has_beep = 0;
13693 for (i = 0; i < spec->num_mixers; i++) {
13694 if (spec->mixers[i] == alc268_beep_mixer) {
13695 has_beep = 1;
13696 break;
13697 }
13698 }
13699
13700 if (has_beep) {
13701 err = snd_hda_attach_beep_device(codec, 0x1);
13702 if (err < 0) {
13703 alc_free(codec);
13704 return err;
13705 }
13706 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
13707 /* override the amp caps for beep generator */
13708 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013709 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
13710 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
13711 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
13712 (0 << AC_AMPCAP_MUTE_SHIFT));
Takashi Iwai22971e32009-02-10 11:56:44 +010013713 }
Takashi Iwaiaef9d312008-02-19 13:16:41 +010013714
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010013715 if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013716 /* check whether NID 0x07 is valid */
13717 unsigned int wcap = get_wcaps(codec, 0x07);
Takashi Iwai85860c02008-02-19 15:00:15 +010013718 int i;
Kailang Yanga361d842007-06-05 12:30:55 +020013719
Takashi Iwaidefb5ab2009-10-07 15:12:27 +020013720 spec->capsrc_nids = alc268_capsrc_nids;
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013721 /* get type */
Takashi Iwaia22d5432009-07-27 12:54:26 +020013722 wcap = get_wcaps_type(wcap);
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013723 if (spec->auto_mic ||
13724 wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013725 spec->adc_nids = alc268_adc_nids_alt;
13726 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
Takashi Iwaidefb5ab2009-10-07 15:12:27 +020013727 if (spec->auto_mic)
13728 fixup_automic_adc(codec);
Takashi Iwaifdbc6622009-08-19 00:18:10 +020013729 if (spec->auto_mic || spec->input_mux->num_items == 1)
13730 add_mixer(spec, alc268_capture_nosrc_mixer);
13731 else
13732 add_mixer(spec, alc268_capture_alt_mixer);
Takashi Iwai3866f0b2008-01-15 12:37:42 +010013733 } else {
13734 spec->adc_nids = alc268_adc_nids;
13735 spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
Takashi Iwaid88897e2008-10-31 15:01:37 +010013736 add_mixer(spec, alc268_capture_mixer);
Kailang Yanga361d842007-06-05 12:30:55 +020013737 }
Takashi Iwai85860c02008-02-19 15:00:15 +010013738 /* set default input source */
13739 for (i = 0; i < spec->num_adc_nids; i++)
13740 snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
13741 0, AC_VERB_SET_CONNECT_SEL,
Herton Ronaldo Krzesinski59085892009-08-11 22:33:09 -030013742 i < spec->num_mux_defs ?
13743 spec->input_mux[i].items[0].index :
Takashi Iwai85860c02008-02-19 15:00:15 +010013744 spec->input_mux->items[0].index);
Kailang Yanga361d842007-06-05 12:30:55 +020013745 }
Takashi Iwai2134ea42008-01-10 16:53:55 +010013746
13747 spec->vmaster_nid = 0x02;
13748
Kailang Yanga361d842007-06-05 12:30:55 +020013749 codec->patch_ops = alc_patch_ops;
13750 if (board_config == ALC268_AUTO)
13751 spec->init_hook = alc268_auto_init;
Kailang Yangea1fb292008-08-26 12:58:38 +020013752
Kailang Yanga361d842007-06-05 12:30:55 +020013753 return 0;
13754}
13755
13756/*
Kailang Yangf6a92242007-12-13 16:52:54 +010013757 * ALC269 channel source setting (2 channel)
13758 */
13759#define ALC269_DIGOUT_NID ALC880_DIGOUT_NID
13760
13761#define alc269_dac_nids alc260_dac_nids
13762
13763static hda_nid_t alc269_adc_nids[1] = {
13764 /* ADC1 */
Kailang Yangf53281e2008-07-18 12:36:43 +020013765 0x08,
13766};
13767
Takashi Iwaie01bf502008-08-21 16:25:07 +020013768static hda_nid_t alc269_capsrc_nids[1] = {
13769 0x23,
13770};
13771
Kailang Yang84898e82010-02-04 14:16:14 +010013772static hda_nid_t alc269vb_adc_nids[1] = {
13773 /* ADC1 */
13774 0x09,
13775};
13776
13777static hda_nid_t alc269vb_capsrc_nids[1] = {
13778 0x22,
13779};
13780
Takashi Iwai66946352010-03-29 17:21:45 +020013781static hda_nid_t alc269_adc_candidates[] = {
13782 0x08, 0x09, 0x07,
13783};
Takashi Iwaie01bf502008-08-21 16:25:07 +020013784
Kailang Yangf6a92242007-12-13 16:52:54 +010013785#define alc269_modes alc260_modes
13786#define alc269_capture_source alc880_lg_lw_capture_source
13787
13788static struct snd_kcontrol_new alc269_base_mixer[] = {
13789 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13790 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13791 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
13792 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
13793 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13794 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13795 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13796 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13797 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13798 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
13799 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
13800 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
13801 { } /* end */
13802};
13803
Kailang Yang60db6b52008-08-26 13:13:00 +020013804static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
13805 /* output mixer control */
13806 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13807 {
13808 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13809 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010013810 .subdevice = HDA_SUBDEV_AMP_FLAG,
Kailang Yang60db6b52008-08-26 13:13:00 +020013811 .info = snd_hda_mixer_amp_switch_info,
13812 .get = snd_hda_mixer_amp_switch_get,
13813 .put = alc268_acer_master_sw_put,
13814 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
13815 },
13816 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13817 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13818 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13819 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13820 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13821 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
Kailang Yang60db6b52008-08-26 13:13:00 +020013822 { }
13823};
13824
Tony Vroon64154832008-11-06 15:08:49 +000013825static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
13826 /* output mixer control */
13827 HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
13828 {
13829 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13830 .name = "Master Playback Switch",
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +010013831 .subdevice = HDA_SUBDEV_AMP_FLAG,
Tony Vroon64154832008-11-06 15:08:49 +000013832 .info = snd_hda_mixer_amp_switch_info,
13833 .get = snd_hda_mixer_amp_switch_get,
13834 .put = alc268_acer_master_sw_put,
13835 .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
13836 },
13837 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
13838 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
13839 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13840 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
13841 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
13842 HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
13843 HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
13844 HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
13845 HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT),
Tony Vroon64154832008-11-06 15:08:49 +000013846 { }
13847};
13848
Kailang Yang84898e82010-02-04 14:16:14 +010013849static struct snd_kcontrol_new alc269_laptop_mixer[] = {
Takashi Iwaiaa202452009-07-03 15:00:54 +020013850 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Darren Salt508f7112009-07-08 15:29:49 +010013851 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Takashi Iwaiaa202452009-07-03 15:00:54 +020013852 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
Darren Salt508f7112009-07-08 15:29:49 +010013853 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yangf53281e2008-07-18 12:36:43 +020013854 { } /* end */
13855};
13856
Kailang Yang84898e82010-02-04 14:16:14 +010013857static struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
13858 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
13859 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13860 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
13861 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
13862 { } /* end */
13863};
13864
Kailang Yangfe3eb0a2010-08-06 10:02:57 +020013865static struct snd_kcontrol_new alc269_asus_mixer[] = {
13866 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
13867 HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT),
13868 { } /* end */
13869};
13870
Kailang Yangf6a92242007-12-13 16:52:54 +010013871/* capture mixer elements */
Kailang Yang84898e82010-02-04 14:16:14 +010013872static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
13873 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
13874 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
13875 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13876 HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT),
13877 { } /* end */
13878};
13879
13880static struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
Kailang Yangf53281e2008-07-18 12:36:43 +020013881 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
13882 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
Takashi Iwai26f5df22008-11-03 17:39:46 +010013883 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13884 { } /* end */
13885};
13886
Kailang Yang84898e82010-02-04 14:16:14 +010013887static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
13888 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
13889 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
13890 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13891 HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT),
13892 { } /* end */
13893};
13894
13895static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
13896 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
13897 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
13898 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
13899 { } /* end */
13900};
13901
Takashi Iwai26f5df22008-11-03 17:39:46 +010013902/* FSC amilo */
Kailang Yang84898e82010-02-04 14:16:14 +010013903#define alc269_fujitsu_mixer alc269_laptop_mixer
Kailang Yangf53281e2008-07-18 12:36:43 +020013904
Kailang Yang60db6b52008-08-26 13:13:00 +020013905static struct hda_verb alc269_quanta_fl1_verbs[] = {
13906 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13907 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13908 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13909 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13910 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13911 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13912 { }
13913};
13914
Tony Vroon64154832008-11-06 15:08:49 +000013915static struct hda_verb alc269_lifebook_verbs[] = {
13916 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
13917 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
13918 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13919 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13920 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13921 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
13922 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
13923 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
13924 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
13925 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
13926 { }
13927};
13928
Kailang Yang60db6b52008-08-26 13:13:00 +020013929/* toggle speaker-output according to the hp-jack state */
13930static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
13931{
13932 unsigned int present;
13933 unsigned char bits;
13934
Wu Fengguang864f92b2009-11-18 12:38:02 +080013935 present = snd_hda_jack_detect(codec, 0x15);
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013936 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yang60db6b52008-08-26 13:13:00 +020013937 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013938 HDA_AMP_MUTE, bits);
Kailang Yang60db6b52008-08-26 13:13:00 +020013939 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013940 HDA_AMP_MUTE, bits);
Kailang Yang60db6b52008-08-26 13:13:00 +020013941
13942 snd_hda_codec_write(codec, 0x20, 0,
13943 AC_VERB_SET_COEF_INDEX, 0x0c);
13944 snd_hda_codec_write(codec, 0x20, 0,
13945 AC_VERB_SET_PROC_COEF, 0x680);
13946
13947 snd_hda_codec_write(codec, 0x20, 0,
13948 AC_VERB_SET_COEF_INDEX, 0x0c);
13949 snd_hda_codec_write(codec, 0x20, 0,
13950 AC_VERB_SET_PROC_COEF, 0x480);
13951}
13952
Tony Vroon64154832008-11-06 15:08:49 +000013953/* toggle speaker-output according to the hp-jacks state */
13954static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
13955{
13956 unsigned int present;
13957 unsigned char bits;
13958
13959 /* Check laptop headphone socket */
Wu Fengguang864f92b2009-11-18 12:38:02 +080013960 present = snd_hda_jack_detect(codec, 0x15);
Tony Vroon64154832008-11-06 15:08:49 +000013961
13962 /* Check port replicator headphone socket */
Wu Fengguang864f92b2009-11-18 12:38:02 +080013963 present |= snd_hda_jack_detect(codec, 0x1a);
Tony Vroon64154832008-11-06 15:08:49 +000013964
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013965 bits = present ? HDA_AMP_MUTE : 0;
Tony Vroon64154832008-11-06 15:08:49 +000013966 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013967 HDA_AMP_MUTE, bits);
Tony Vroon64154832008-11-06 15:08:49 +000013968 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020013969 HDA_AMP_MUTE, bits);
Tony Vroon64154832008-11-06 15:08:49 +000013970
13971 snd_hda_codec_write(codec, 0x20, 0,
13972 AC_VERB_SET_COEF_INDEX, 0x0c);
13973 snd_hda_codec_write(codec, 0x20, 0,
13974 AC_VERB_SET_PROC_COEF, 0x680);
13975
13976 snd_hda_codec_write(codec, 0x20, 0,
13977 AC_VERB_SET_COEF_INDEX, 0x0c);
13978 snd_hda_codec_write(codec, 0x20, 0,
13979 AC_VERB_SET_PROC_COEF, 0x480);
13980}
13981
Tony Vroon64154832008-11-06 15:08:49 +000013982static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
13983{
13984 unsigned int present_laptop;
13985 unsigned int present_dock;
13986
Wu Fengguang864f92b2009-11-18 12:38:02 +080013987 present_laptop = snd_hda_jack_detect(codec, 0x18);
13988 present_dock = snd_hda_jack_detect(codec, 0x1b);
Tony Vroon64154832008-11-06 15:08:49 +000013989
13990 /* Laptop mic port overrides dock mic port, design decision */
13991 if (present_dock)
13992 snd_hda_codec_write(codec, 0x23, 0,
13993 AC_VERB_SET_CONNECT_SEL, 0x3);
13994 if (present_laptop)
13995 snd_hda_codec_write(codec, 0x23, 0,
13996 AC_VERB_SET_CONNECT_SEL, 0x0);
13997 if (!present_dock && !present_laptop)
13998 snd_hda_codec_write(codec, 0x23, 0,
13999 AC_VERB_SET_CONNECT_SEL, 0x1);
14000}
14001
Kailang Yang60db6b52008-08-26 13:13:00 +020014002static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
14003 unsigned int res)
14004{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014005 switch (res >> 26) {
14006 case ALC880_HP_EVENT:
Kailang Yang60db6b52008-08-26 13:13:00 +020014007 alc269_quanta_fl1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014008 break;
14009 case ALC880_MIC_EVENT:
14010 alc_mic_automute(codec);
14011 break;
14012 }
Kailang Yang60db6b52008-08-26 13:13:00 +020014013}
14014
Tony Vroon64154832008-11-06 15:08:49 +000014015static void alc269_lifebook_unsol_event(struct hda_codec *codec,
14016 unsigned int res)
14017{
14018 if ((res >> 26) == ALC880_HP_EVENT)
14019 alc269_lifebook_speaker_automute(codec);
14020 if ((res >> 26) == ALC880_MIC_EVENT)
14021 alc269_lifebook_mic_autoswitch(codec);
14022}
14023
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014024static void alc269_quanta_fl1_setup(struct hda_codec *codec)
14025{
14026 struct alc_spec *spec = codec->spec;
Takashi Iwai20645d72010-03-02 11:14:01 +010014027 spec->autocfg.hp_pins[0] = 0x15;
14028 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014029 spec->ext_mic.pin = 0x18;
14030 spec->ext_mic.mux_idx = 0;
14031 spec->int_mic.pin = 0x19;
14032 spec->int_mic.mux_idx = 1;
14033 spec->auto_mic = 1;
14034}
14035
Kailang Yang60db6b52008-08-26 13:13:00 +020014036static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
14037{
14038 alc269_quanta_fl1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014039 alc_mic_automute(codec);
Kailang Yang60db6b52008-08-26 13:13:00 +020014040}
14041
Tony Vroon64154832008-11-06 15:08:49 +000014042static void alc269_lifebook_init_hook(struct hda_codec *codec)
14043{
14044 alc269_lifebook_speaker_automute(codec);
14045 alc269_lifebook_mic_autoswitch(codec);
14046}
14047
Kailang Yang84898e82010-02-04 14:16:14 +010014048static struct hda_verb alc269_laptop_dmic_init_verbs[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020014049 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14050 {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
14051 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14052 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14053 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14054 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14055 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14056 {}
14057};
14058
Kailang Yang84898e82010-02-04 14:16:14 +010014059static struct hda_verb alc269_laptop_amic_init_verbs[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020014060 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
14061 {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
14062 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14063 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
14064 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14065 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14066 {}
14067};
14068
Kailang Yang84898e82010-02-04 14:16:14 +010014069static struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
14070 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
14071 {0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
14072 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14073 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14074 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14075 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14076 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14077 {}
14078};
14079
14080static struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
14081 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
14082 {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
14083 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
14084 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
14085 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14086 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14087 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14088 {}
14089};
14090
Kailang Yangfe3eb0a2010-08-06 10:02:57 +020014091static struct hda_verb alc271_acer_dmic_verbs[] = {
14092 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
14093 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
14094 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14095 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14096 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14097 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14098 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00},
14099 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
14100 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
14101 {0x22, AC_VERB_SET_CONNECT_SEL, 6},
14102 { }
14103};
14104
Kailang Yang60db6b52008-08-26 13:13:00 +020014105/* toggle speaker-output according to the hp-jack state */
14106static void alc269_speaker_automute(struct hda_codec *codec)
14107{
Kailang Yangebb83ee2009-12-17 12:23:00 +010014108 struct alc_spec *spec = codec->spec;
14109 unsigned int nid = spec->autocfg.hp_pins[0];
Kailang Yang60db6b52008-08-26 13:13:00 +020014110 unsigned int present;
14111 unsigned char bits;
14112
Kailang Yangebb83ee2009-12-17 12:23:00 +010014113 present = snd_hda_jack_detect(codec, nid);
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020014114 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yang60db6b52008-08-26 13:13:00 +020014115 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020014116 HDA_AMP_MUTE, bits);
Kailang Yang60db6b52008-08-26 13:13:00 +020014117 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020014118 HDA_AMP_MUTE, bits);
Kailang Yang60db6b52008-08-26 13:13:00 +020014119}
14120
Kailang Yang60db6b52008-08-26 13:13:00 +020014121/* unsolicited event for HP jack sensing */
Kailang Yang84898e82010-02-04 14:16:14 +010014122static void alc269_laptop_unsol_event(struct hda_codec *codec,
Kailang Yang60db6b52008-08-26 13:13:00 +020014123 unsigned int res)
14124{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014125 switch (res >> 26) {
14126 case ALC880_HP_EVENT:
Kailang Yang60db6b52008-08-26 13:13:00 +020014127 alc269_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014128 break;
14129 case ALC880_MIC_EVENT:
14130 alc_mic_automute(codec);
14131 break;
14132 }
Kailang Yang60db6b52008-08-26 13:13:00 +020014133}
14134
Kailang Yang226b1ec2010-04-09 11:01:20 +020014135static void alc269_laptop_amic_setup(struct hda_codec *codec)
14136{
14137 struct alc_spec *spec = codec->spec;
14138 spec->autocfg.hp_pins[0] = 0x15;
14139 spec->autocfg.speaker_pins[0] = 0x14;
14140 spec->ext_mic.pin = 0x18;
14141 spec->ext_mic.mux_idx = 0;
14142 spec->int_mic.pin = 0x19;
14143 spec->int_mic.mux_idx = 1;
14144 spec->auto_mic = 1;
14145}
14146
Kailang Yang84898e82010-02-04 14:16:14 +010014147static void alc269_laptop_dmic_setup(struct hda_codec *codec)
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014148{
14149 struct alc_spec *spec = codec->spec;
Takashi Iwai20645d72010-03-02 11:14:01 +010014150 spec->autocfg.hp_pins[0] = 0x15;
14151 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014152 spec->ext_mic.pin = 0x18;
14153 spec->ext_mic.mux_idx = 0;
14154 spec->int_mic.pin = 0x12;
14155 spec->int_mic.mux_idx = 5;
14156 spec->auto_mic = 1;
14157}
14158
Kailang Yang226b1ec2010-04-09 11:01:20 +020014159static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
Kailang Yang84898e82010-02-04 14:16:14 +010014160{
14161 struct alc_spec *spec = codec->spec;
Kailang Yang226b1ec2010-04-09 11:01:20 +020014162 spec->autocfg.hp_pins[0] = 0x21;
Takashi Iwai20645d72010-03-02 11:14:01 +010014163 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014164 spec->ext_mic.pin = 0x18;
14165 spec->ext_mic.mux_idx = 0;
14166 spec->int_mic.pin = 0x19;
14167 spec->int_mic.mux_idx = 1;
14168 spec->auto_mic = 1;
14169}
14170
Kailang Yang226b1ec2010-04-09 11:01:20 +020014171static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
14172{
14173 struct alc_spec *spec = codec->spec;
14174 spec->autocfg.hp_pins[0] = 0x21;
14175 spec->autocfg.speaker_pins[0] = 0x14;
14176 spec->ext_mic.pin = 0x18;
14177 spec->ext_mic.mux_idx = 0;
14178 spec->int_mic.pin = 0x12;
14179 spec->int_mic.mux_idx = 6;
14180 spec->auto_mic = 1;
14181}
14182
Kailang Yang84898e82010-02-04 14:16:14 +010014183static void alc269_laptop_inithook(struct hda_codec *codec)
Kailang Yang60db6b52008-08-26 13:13:00 +020014184{
14185 alc269_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014186 alc_mic_automute(codec);
Kailang Yang60db6b52008-08-26 13:13:00 +020014187}
14188
Kailang Yangf6a92242007-12-13 16:52:54 +010014189/*
14190 * generic initialization of ADC, input mixers and output mixers
14191 */
14192static struct hda_verb alc269_init_verbs[] = {
14193 /*
14194 * Unmute ADC0 and set the default input to mic-in
14195 */
Kailang Yang84898e82010-02-04 14:16:14 +010014196 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangf6a92242007-12-13 16:52:54 +010014197
14198 /*
Kailang Yang84898e82010-02-04 14:16:14 +010014199 * Set up output mixers (0x02 - 0x03)
Kailang Yangf6a92242007-12-13 16:52:54 +010014200 */
14201 /* set vol=0 to output mixers */
14202 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14203 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14204
14205 /* set up input amps for analog loopback */
14206 /* Amp Indices: DAC = 0, mixer = 1 */
14207 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14208 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14209 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14210 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14211 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14212 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14213
14214 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14215 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14216 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14217 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14218 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14219 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14220 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14221
14222 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14223 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangf6a92242007-12-13 16:52:54 +010014224
Kailang Yang84898e82010-02-04 14:16:14 +010014225 /* FIXME: use Mux-type input source selection */
Kailang Yangf6a92242007-12-13 16:52:54 +010014226 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
14227 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
Kailang Yang84898e82010-02-04 14:16:14 +010014228 {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangf6a92242007-12-13 16:52:54 +010014229
14230 /* set EAPD */
14231 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
Kailang Yang84898e82010-02-04 14:16:14 +010014232 { }
14233};
14234
14235static struct hda_verb alc269vb_init_verbs[] = {
14236 /*
14237 * Unmute ADC0 and set the default input to mic-in
14238 */
14239 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14240
14241 /*
14242 * Set up output mixers (0x02 - 0x03)
14243 */
14244 /* set vol=0 to output mixers */
14245 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14246 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
14247
14248 /* set up input amps for analog loopback */
14249 /* Amp Indices: DAC = 0, mixer = 1 */
14250 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14251 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14252 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14253 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14254 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
14255 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
14256
14257 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14258 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
14259 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
14260 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14261 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
14262 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14263 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
14264
14265 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14266 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
14267
14268 /* FIXME: use Mux-type input source selection */
14269 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
14270 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
14271 {0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
14272
14273 /* set EAPD */
14274 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
Kailang Yangf6a92242007-12-13 16:52:54 +010014275 { }
14276};
14277
Takashi Iwai9d0b71b2009-08-24 14:10:30 +020014278#define alc269_auto_create_multi_out_ctls \
14279 alc268_auto_create_multi_out_ctls
Takashi Iwai05f5f472009-08-25 13:10:18 +020014280#define alc269_auto_create_input_ctls \
14281 alc268_auto_create_input_ctls
Kailang Yangf6a92242007-12-13 16:52:54 +010014282
14283#ifdef CONFIG_SND_HDA_POWER_SAVE
14284#define alc269_loopbacks alc880_loopbacks
14285#endif
14286
Sasha Alexandrdef319f2009-06-16 16:00:15 -040014287/* pcm configuration: identical with ALC880 */
Kailang Yangf6a92242007-12-13 16:52:54 +010014288#define alc269_pcm_analog_playback alc880_pcm_analog_playback
14289#define alc269_pcm_analog_capture alc880_pcm_analog_capture
14290#define alc269_pcm_digital_playback alc880_pcm_digital_playback
14291#define alc269_pcm_digital_capture alc880_pcm_digital_capture
14292
Takashi Iwaif03d3112009-03-05 14:18:16 +010014293static struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
14294 .substreams = 1,
14295 .channels_min = 2,
14296 .channels_max = 8,
14297 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
14298 /* NID is set in alc_build_pcms */
14299 .ops = {
14300 .open = alc880_playback_pcm_open,
14301 .prepare = alc880_playback_pcm_prepare,
14302 .cleanup = alc880_playback_pcm_cleanup
14303 },
14304};
14305
14306static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
14307 .substreams = 1,
14308 .channels_min = 2,
14309 .channels_max = 2,
14310 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
14311 /* NID is set in alc_build_pcms */
14312};
14313
Takashi Iwaiad358792010-03-30 18:00:59 +020014314#ifdef CONFIG_SND_HDA_POWER_SAVE
14315static int alc269_mic2_for_mute_led(struct hda_codec *codec)
14316{
14317 switch (codec->subsystem_id) {
14318 case 0x103c1586:
14319 return 1;
14320 }
14321 return 0;
14322}
14323
14324static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
14325{
14326 /* update mute-LED according to the speaker mute state */
14327 if (nid == 0x01 || nid == 0x14) {
14328 int pinval;
14329 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
14330 HDA_AMP_MUTE)
14331 pinval = 0x24;
14332 else
14333 pinval = 0x20;
14334 /* mic2 vref pin is used for mute LED control */
Takashi Iwaia68d5a52010-03-30 18:03:44 +020014335 snd_hda_codec_update_cache(codec, 0x19, 0,
14336 AC_VERB_SET_PIN_WIDGET_CONTROL,
14337 pinval);
Takashi Iwaiad358792010-03-30 18:00:59 +020014338 }
14339 return alc_check_power_status(codec, nid);
14340}
14341#endif /* CONFIG_SND_HDA_POWER_SAVE */
14342
Takashi Iwai840b64c2010-07-13 22:49:01 +020014343static int alc275_setup_dual_adc(struct hda_codec *codec)
14344{
14345 struct alc_spec *spec = codec->spec;
14346
14347 if (codec->vendor_id != 0x10ec0275 || !spec->auto_mic)
14348 return 0;
14349 if ((spec->ext_mic.pin >= 0x18 && spec->int_mic.pin <= 0x13) ||
14350 (spec->ext_mic.pin <= 0x12 && spec->int_mic.pin >= 0x18)) {
14351 if (spec->ext_mic.pin <= 0x12) {
14352 spec->private_adc_nids[0] = 0x08;
14353 spec->private_adc_nids[1] = 0x11;
14354 spec->private_capsrc_nids[0] = 0x23;
14355 spec->private_capsrc_nids[1] = 0x22;
14356 } else {
14357 spec->private_adc_nids[0] = 0x11;
14358 spec->private_adc_nids[1] = 0x08;
14359 spec->private_capsrc_nids[0] = 0x22;
14360 spec->private_capsrc_nids[1] = 0x23;
14361 }
14362 spec->adc_nids = spec->private_adc_nids;
14363 spec->capsrc_nids = spec->private_capsrc_nids;
14364 spec->num_adc_nids = 2;
14365 spec->dual_adc_switch = 1;
14366 snd_printdd("realtek: enabling dual ADC switchg (%02x:%02x)\n",
14367 spec->adc_nids[0], spec->adc_nids[1]);
14368 return 1;
14369 }
14370 return 0;
14371}
14372
Kailang Yangf6a92242007-12-13 16:52:54 +010014373/*
14374 * BIOS auto configuration
14375 */
14376static int alc269_parse_auto_config(struct hda_codec *codec)
14377{
14378 struct alc_spec *spec = codec->spec;
Takashi Iwaicfb9fb52009-02-06 17:34:03 +010014379 int err;
Kailang Yangf6a92242007-12-13 16:52:54 +010014380 static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
14381
14382 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
14383 alc269_ignore);
14384 if (err < 0)
14385 return err;
14386
14387 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
14388 if (err < 0)
14389 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020014390 err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
Kailang Yangf6a92242007-12-13 16:52:54 +010014391 if (err < 0)
14392 return err;
14393
14394 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
14395
Takashi Iwai757899a2010-07-30 10:48:14 +020014396 alc_auto_parse_digital(codec);
Kailang Yangf6a92242007-12-13 16:52:54 +010014397
Takashi Iwai603c4012008-07-30 15:01:44 +020014398 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010014399 add_mixer(spec, spec->kctls.list);
Kailang Yangf6a92242007-12-13 16:52:54 +010014400
Kailang Yang84898e82010-02-04 14:16:14 +010014401 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) {
14402 add_verb(spec, alc269vb_init_verbs);
Kailang Yang6227cdc2010-02-25 08:36:52 +010014403 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
Kailang Yang84898e82010-02-04 14:16:14 +010014404 } else {
14405 add_verb(spec, alc269_init_verbs);
Kailang Yang6227cdc2010-02-25 08:36:52 +010014406 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Kailang Yang84898e82010-02-04 14:16:14 +010014407 }
14408
Kailang Yangf6a92242007-12-13 16:52:54 +010014409 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020014410 spec->input_mux = &spec->private_imux[0];
Takashi Iwai840b64c2010-07-13 22:49:01 +020014411
14412 if (!alc275_setup_dual_adc(codec))
14413 fillup_priv_adc_nids(codec, alc269_adc_candidates,
14414 sizeof(alc269_adc_candidates));
Takashi Iwai66946352010-03-29 17:21:45 +020014415
Takashi Iwaie01bf502008-08-21 16:25:07 +020014416 /* set default input source */
Takashi Iwai840b64c2010-07-13 22:49:01 +020014417 if (!spec->dual_adc_switch)
Takashi Iwai748cce42010-08-04 07:37:39 +020014418 select_or_unmute_capsrc(codec, spec->capsrc_nids[0],
14419 spec->input_mux->items[0].index);
Kailang Yangf6a92242007-12-13 16:52:54 +010014420
14421 err = alc_auto_add_mic_boost(codec);
14422 if (err < 0)
14423 return err;
14424
Takashi Iwai7e0e44d2009-02-19 08:15:49 +010014425 if (!spec->cap_mixer && !spec->no_analog)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020014426 set_capture_mixer(codec);
Kailang Yangf53281e2008-07-18 12:36:43 +020014427
Kailang Yangf6a92242007-12-13 16:52:54 +010014428 return 1;
14429}
14430
Takashi Iwaie9af4f32009-08-29 23:23:08 +020014431#define alc269_auto_init_multi_out alc268_auto_init_multi_out
14432#define alc269_auto_init_hp_out alc268_auto_init_hp_out
Kailang Yangf6a92242007-12-13 16:52:54 +010014433#define alc269_auto_init_analog_input alc882_auto_init_analog_input
14434
14435
14436/* init callback for auto-configuration model -- overriding the default init */
14437static void alc269_auto_init(struct hda_codec *codec)
14438{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010014439 struct alc_spec *spec = codec->spec;
Kailang Yangf6a92242007-12-13 16:52:54 +010014440 alc269_auto_init_multi_out(codec);
14441 alc269_auto_init_hp_out(codec);
14442 alc269_auto_init_analog_input(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +020014443 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010014444 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020014445 alc_inithook(codec);
Kailang Yangf6a92242007-12-13 16:52:54 +010014446}
14447
Takashi Iwaiff818c22010-04-12 08:59:25 +020014448enum {
14449 ALC269_FIXUP_SONY_VAIO,
14450};
14451
Takashi Iwaiff818c22010-04-12 08:59:25 +020014452static const struct alc_fixup alc269_fixups[] = {
14453 [ALC269_FIXUP_SONY_VAIO] = {
Takashi Iwai73413b12010-08-30 09:39:57 +020014454 .verbs = (const struct hda_verb[]) {
14455 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
14456 {}
14457 }
Takashi Iwaiff818c22010-04-12 08:59:25 +020014458 },
14459};
14460
14461static struct snd_pci_quirk alc269_fixup_tbl[] = {
14462 SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
David Henningssondbbcbc02010-08-23 08:14:35 +020014463 SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
Takashi Iwaiff818c22010-04-12 08:59:25 +020014464 {}
14465};
14466
14467
Kailang Yangf6a92242007-12-13 16:52:54 +010014468/*
14469 * configuration and preset
14470 */
14471static const char *alc269_models[ALC269_MODEL_LAST] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020014472 [ALC269_BASIC] = "basic",
Takashi Iwai2922c9a2008-08-27 18:12:42 +020014473 [ALC269_QUANTA_FL1] = "quanta",
Kailang Yang84898e82010-02-04 14:16:14 +010014474 [ALC269_AMIC] = "laptop-amic",
14475 [ALC269_DMIC] = "laptop-dmic",
Tony Vroon64154832008-11-06 15:08:49 +000014476 [ALC269_FUJITSU] = "fujitsu",
Takashi Iwai3d3792c2009-09-11 07:50:47 +020014477 [ALC269_LIFEBOOK] = "lifebook",
14478 [ALC269_AUTO] = "auto",
Kailang Yangf6a92242007-12-13 16:52:54 +010014479};
14480
14481static struct snd_pci_quirk alc269_cfg_tbl[] = {
Kailang Yang60db6b52008-08-26 13:13:00 +020014482 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
Kailang Yangfe3eb0a2010-08-06 10:02:57 +020014483 SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER),
Kailang Yangf53281e2008-07-18 12:36:43 +020014484 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
Kailang Yang84898e82010-02-04 14:16:14 +010014485 ALC269_AMIC),
14486 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
14487 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
14488 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
14489 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
14490 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
14491 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
14492 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
14493 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
14494 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
14495 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_AMIC),
14496 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
14497 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
14498 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
14499 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
14500 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
14501 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
14502 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
14503 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
14504 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
14505 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
14506 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
14507 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
14508 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
14509 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
14510 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
14511 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
14512 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
14513 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
14514 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
14515 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
14516 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
14517 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
14518 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
14519 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
14520 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
14521 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
Kailang Yangf53281e2008-07-18 12:36:43 +020014522 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
Kailang Yang84898e82010-02-04 14:16:14 +010014523 ALC269_DMIC),
Kailang Yang60db6b52008-08-26 13:13:00 +020014524 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
Kailang Yang84898e82010-02-04 14:16:14 +010014525 ALC269_DMIC),
14526 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
14527 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
Takashi Iwaiff818c22010-04-12 08:59:25 +020014528 SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
Tony Vroon64154832008-11-06 15:08:49 +000014529 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
Kailang Yang61c2d2b2010-02-25 08:49:06 +010014530 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
14531 SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
14532 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC),
14533 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC),
14534 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC),
14535 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC),
Kailang Yangf6a92242007-12-13 16:52:54 +010014536 {}
14537};
14538
14539static struct alc_config_preset alc269_presets[] = {
14540 [ALC269_BASIC] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010014541 .mixers = { alc269_base_mixer },
Kailang Yangf6a92242007-12-13 16:52:54 +010014542 .init_verbs = { alc269_init_verbs },
14543 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14544 .dac_nids = alc269_dac_nids,
14545 .hp_nid = 0x03,
14546 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14547 .channel_mode = alc269_modes,
14548 .input_mux = &alc269_capture_source,
14549 },
Kailang Yang60db6b52008-08-26 13:13:00 +020014550 [ALC269_QUANTA_FL1] = {
14551 .mixers = { alc269_quanta_fl1_mixer },
14552 .init_verbs = { alc269_init_verbs, alc269_quanta_fl1_verbs },
14553 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14554 .dac_nids = alc269_dac_nids,
14555 .hp_nid = 0x03,
14556 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14557 .channel_mode = alc269_modes,
14558 .input_mux = &alc269_capture_source,
14559 .unsol_event = alc269_quanta_fl1_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020014560 .setup = alc269_quanta_fl1_setup,
Kailang Yang60db6b52008-08-26 13:13:00 +020014561 .init_hook = alc269_quanta_fl1_init_hook,
14562 },
Kailang Yang84898e82010-02-04 14:16:14 +010014563 [ALC269_AMIC] = {
14564 .mixers = { alc269_laptop_mixer },
14565 .cap_mixer = alc269_laptop_analog_capture_mixer,
Kailang Yangf53281e2008-07-18 12:36:43 +020014566 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010014567 alc269_laptop_amic_init_verbs },
Kailang Yangf53281e2008-07-18 12:36:43 +020014568 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14569 .dac_nids = alc269_dac_nids,
14570 .hp_nid = 0x03,
14571 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14572 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010014573 .unsol_event = alc269_laptop_unsol_event,
14574 .setup = alc269_laptop_amic_setup,
14575 .init_hook = alc269_laptop_inithook,
Kailang Yangf53281e2008-07-18 12:36:43 +020014576 },
Kailang Yang84898e82010-02-04 14:16:14 +010014577 [ALC269_DMIC] = {
14578 .mixers = { alc269_laptop_mixer },
14579 .cap_mixer = alc269_laptop_digital_capture_mixer,
Kailang Yangf53281e2008-07-18 12:36:43 +020014580 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010014581 alc269_laptop_dmic_init_verbs },
Kailang Yangf53281e2008-07-18 12:36:43 +020014582 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14583 .dac_nids = alc269_dac_nids,
14584 .hp_nid = 0x03,
14585 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14586 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010014587 .unsol_event = alc269_laptop_unsol_event,
14588 .setup = alc269_laptop_dmic_setup,
14589 .init_hook = alc269_laptop_inithook,
14590 },
14591 [ALC269VB_AMIC] = {
14592 .mixers = { alc269vb_laptop_mixer },
14593 .cap_mixer = alc269vb_laptop_analog_capture_mixer,
14594 .init_verbs = { alc269vb_init_verbs,
14595 alc269vb_laptop_amic_init_verbs },
14596 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14597 .dac_nids = alc269_dac_nids,
14598 .hp_nid = 0x03,
14599 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14600 .channel_mode = alc269_modes,
14601 .unsol_event = alc269_laptop_unsol_event,
Kailang Yang226b1ec2010-04-09 11:01:20 +020014602 .setup = alc269vb_laptop_amic_setup,
Kailang Yang84898e82010-02-04 14:16:14 +010014603 .init_hook = alc269_laptop_inithook,
14604 },
14605 [ALC269VB_DMIC] = {
14606 .mixers = { alc269vb_laptop_mixer },
14607 .cap_mixer = alc269vb_laptop_digital_capture_mixer,
14608 .init_verbs = { alc269vb_init_verbs,
14609 alc269vb_laptop_dmic_init_verbs },
14610 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14611 .dac_nids = alc269_dac_nids,
14612 .hp_nid = 0x03,
14613 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14614 .channel_mode = alc269_modes,
14615 .unsol_event = alc269_laptop_unsol_event,
14616 .setup = alc269vb_laptop_dmic_setup,
14617 .init_hook = alc269_laptop_inithook,
Kailang Yangf53281e2008-07-18 12:36:43 +020014618 },
Takashi Iwai26f5df22008-11-03 17:39:46 +010014619 [ALC269_FUJITSU] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010014620 .mixers = { alc269_fujitsu_mixer },
Kailang Yang84898e82010-02-04 14:16:14 +010014621 .cap_mixer = alc269_laptop_digital_capture_mixer,
Takashi Iwai26f5df22008-11-03 17:39:46 +010014622 .init_verbs = { alc269_init_verbs,
Kailang Yang84898e82010-02-04 14:16:14 +010014623 alc269_laptop_dmic_init_verbs },
Takashi Iwai26f5df22008-11-03 17:39:46 +010014624 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14625 .dac_nids = alc269_dac_nids,
14626 .hp_nid = 0x03,
14627 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14628 .channel_mode = alc269_modes,
Kailang Yang84898e82010-02-04 14:16:14 +010014629 .unsol_event = alc269_laptop_unsol_event,
14630 .setup = alc269_laptop_dmic_setup,
14631 .init_hook = alc269_laptop_inithook,
Takashi Iwai26f5df22008-11-03 17:39:46 +010014632 },
Tony Vroon64154832008-11-06 15:08:49 +000014633 [ALC269_LIFEBOOK] = {
14634 .mixers = { alc269_lifebook_mixer },
14635 .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
14636 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14637 .dac_nids = alc269_dac_nids,
14638 .hp_nid = 0x03,
14639 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14640 .channel_mode = alc269_modes,
14641 .input_mux = &alc269_capture_source,
14642 .unsol_event = alc269_lifebook_unsol_event,
14643 .init_hook = alc269_lifebook_init_hook,
14644 },
Kailang Yangfe3eb0a2010-08-06 10:02:57 +020014645 [ALC271_ACER] = {
14646 .mixers = { alc269_asus_mixer },
14647 .cap_mixer = alc269vb_laptop_digital_capture_mixer,
14648 .init_verbs = { alc269_init_verbs, alc271_acer_dmic_verbs },
14649 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
14650 .dac_nids = alc269_dac_nids,
14651 .adc_nids = alc262_dmic_adc_nids,
14652 .num_adc_nids = ARRAY_SIZE(alc262_dmic_adc_nids),
14653 .capsrc_nids = alc262_dmic_capsrc_nids,
14654 .num_channel_mode = ARRAY_SIZE(alc269_modes),
14655 .channel_mode = alc269_modes,
14656 .input_mux = &alc269_capture_source,
14657 .dig_out_nid = ALC880_DIGOUT_NID,
14658 .unsol_event = alc_sku_unsol_event,
14659 .setup = alc269vb_laptop_dmic_setup,
14660 .init_hook = alc_inithook,
14661 },
Kailang Yangf6a92242007-12-13 16:52:54 +010014662};
14663
14664static int patch_alc269(struct hda_codec *codec)
14665{
14666 struct alc_spec *spec;
14667 int board_config;
14668 int err;
Kailang Yang84898e82010-02-04 14:16:14 +010014669 int is_alc269vb = 0;
Kailang Yangf6a92242007-12-13 16:52:54 +010014670
14671 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
14672 if (spec == NULL)
14673 return -ENOMEM;
14674
14675 codec->spec = spec;
14676
Kailang Yangda00c242010-03-19 11:23:45 +010014677 alc_auto_parse_customize_define(codec);
14678
Kailang Yang274693f2009-12-03 10:07:50 +010014679 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
Kailang Yangc027ddc2010-03-19 11:33:06 +010014680 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
14681 spec->cdefine.platform_type == 1)
14682 alc_codec_rename(codec, "ALC271X");
14683 else
14684 alc_codec_rename(codec, "ALC259");
Kailang Yang84898e82010-02-04 14:16:14 +010014685 is_alc269vb = 1;
Kailang Yangc027ddc2010-03-19 11:33:06 +010014686 } else
14687 alc_fix_pll_init(codec, 0x20, 0x04, 15);
Kailang Yang274693f2009-12-03 10:07:50 +010014688
Kailang Yangf6a92242007-12-13 16:52:54 +010014689 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
14690 alc269_models,
14691 alc269_cfg_tbl);
14692
14693 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020014694 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
14695 codec->chip_name);
Kailang Yangf6a92242007-12-13 16:52:54 +010014696 board_config = ALC269_AUTO;
14697 }
14698
Takashi Iwaiff818c22010-04-12 08:59:25 +020014699 if (board_config == ALC269_AUTO)
14700 alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 1);
14701
Kailang Yangf6a92242007-12-13 16:52:54 +010014702 if (board_config == ALC269_AUTO) {
14703 /* automatic parse from the BIOS config */
14704 err = alc269_parse_auto_config(codec);
14705 if (err < 0) {
14706 alc_free(codec);
14707 return err;
14708 } else if (!err) {
14709 printk(KERN_INFO
14710 "hda_codec: Cannot set up configuration "
14711 "from BIOS. Using base mode...\n");
14712 board_config = ALC269_BASIC;
14713 }
14714 }
14715
Takashi Iwaidc1eae22010-07-29 15:30:02 +020014716 if (has_cdefine_beep(codec)) {
Takashi Iwai8af25912010-07-28 17:37:16 +020014717 err = snd_hda_attach_beep_device(codec, 0x1);
14718 if (err < 0) {
14719 alc_free(codec);
14720 return err;
14721 }
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090014722 }
14723
Kailang Yangf6a92242007-12-13 16:52:54 +010014724 if (board_config != ALC269_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020014725 setup_preset(codec, &alc269_presets[board_config]);
Kailang Yangf6a92242007-12-13 16:52:54 +010014726
Kailang Yang84898e82010-02-04 14:16:14 +010014727 if (board_config == ALC269_QUANTA_FL1) {
Takashi Iwaif03d3112009-03-05 14:18:16 +010014728 /* Due to a hardware problem on Lenovo Ideadpad, we need to
14729 * fix the sample rate of analog I/O to 44.1kHz
14730 */
14731 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
14732 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
Takashi Iwai840b64c2010-07-13 22:49:01 +020014733 } else if (spec->dual_adc_switch) {
14734 spec->stream_analog_playback = &alc269_pcm_analog_playback;
14735 /* switch ADC dynamically */
14736 spec->stream_analog_capture = &dualmic_pcm_analog_capture;
Takashi Iwaif03d3112009-03-05 14:18:16 +010014737 } else {
14738 spec->stream_analog_playback = &alc269_pcm_analog_playback;
14739 spec->stream_analog_capture = &alc269_pcm_analog_capture;
14740 }
Kailang Yangf6a92242007-12-13 16:52:54 +010014741 spec->stream_digital_playback = &alc269_pcm_digital_playback;
14742 spec->stream_digital_capture = &alc269_pcm_digital_capture;
14743
Takashi Iwai66946352010-03-29 17:21:45 +020014744 if (!spec->adc_nids) { /* wasn't filled automatically? use default */
14745 if (!is_alc269vb) {
14746 spec->adc_nids = alc269_adc_nids;
14747 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
14748 spec->capsrc_nids = alc269_capsrc_nids;
14749 } else {
14750 spec->adc_nids = alc269vb_adc_nids;
14751 spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
14752 spec->capsrc_nids = alc269vb_capsrc_nids;
14753 }
Kailang Yang84898e82010-02-04 14:16:14 +010014754 }
14755
Takashi Iwaif9e336f2008-10-31 16:37:07 +010014756 if (!spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020014757 set_capture_mixer(codec);
Takashi Iwaidc1eae22010-07-29 15:30:02 +020014758 if (has_cdefine_beep(codec))
Kailang Yangda00c242010-03-19 11:23:45 +010014759 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
Kailang Yangf6a92242007-12-13 16:52:54 +010014760
Takashi Iwaiff818c22010-04-12 08:59:25 +020014761 if (board_config == ALC269_AUTO)
14762 alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0);
14763
Takashi Iwai100d5eb2009-08-10 11:55:51 +020014764 spec->vmaster_nid = 0x02;
14765
Kailang Yangf6a92242007-12-13 16:52:54 +010014766 codec->patch_ops = alc_patch_ops;
14767 if (board_config == ALC269_AUTO)
14768 spec->init_hook = alc269_auto_init;
14769#ifdef CONFIG_SND_HDA_POWER_SAVE
14770 if (!spec->loopback.amplist)
14771 spec->loopback.amplist = alc269_loopbacks;
Takashi Iwaiad358792010-03-30 18:00:59 +020014772 if (alc269_mic2_for_mute_led(codec))
14773 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
Kailang Yangf6a92242007-12-13 16:52:54 +010014774#endif
14775
14776 return 0;
14777}
14778
14779/*
Kailang Yangdf694da2005-12-05 19:42:22 +010014780 * ALC861 channel source setting (2/6 channel selection for 3-stack)
14781 */
14782
14783/*
14784 * set the path ways for 2 channel output
14785 * need to set the codec line out and mic 1 pin widgets to inputs
14786 */
14787static struct hda_verb alc861_threestack_ch2_init[] = {
14788 /* set pin widget 1Ah (line in) for input */
14789 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014790 /* set pin widget 18h (mic1/2) for input, for mic also enable
14791 * the vref
14792 */
Kailang Yangdf694da2005-12-05 19:42:22 +010014793 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14794
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014795 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
14796#if 0
14797 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14798 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
14799#endif
Kailang Yangdf694da2005-12-05 19:42:22 +010014800 { } /* end */
14801};
14802/*
14803 * 6ch mode
14804 * need to set the codec line out and mic 1 pin widgets to outputs
14805 */
14806static struct hda_verb alc861_threestack_ch6_init[] = {
14807 /* set pin widget 1Ah (line in) for output (Back Surround)*/
14808 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14809 /* set pin widget 18h (mic1) for output (CLFE)*/
14810 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14811
14812 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014813 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010014814
Takashi Iwai9c7f8522006-06-28 15:08:22 +020014815 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
14816#if 0
14817 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14818 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
14819#endif
Kailang Yangdf694da2005-12-05 19:42:22 +010014820 { } /* end */
14821};
14822
14823static struct hda_channel_mode alc861_threestack_modes[2] = {
14824 { 2, alc861_threestack_ch2_init },
14825 { 6, alc861_threestack_ch6_init },
14826};
Takashi Iwai22309c32006-08-09 16:57:28 +020014827/* Set mic1 as input and unmute the mixer */
14828static struct hda_verb alc861_uniwill_m31_ch2_init[] = {
14829 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14830 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14831 { } /* end */
14832};
14833/* Set mic1 as output and mute mixer */
14834static struct hda_verb alc861_uniwill_m31_ch4_init[] = {
14835 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14836 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14837 { } /* end */
14838};
14839
14840static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
14841 { 2, alc861_uniwill_m31_ch2_init },
14842 { 4, alc861_uniwill_m31_ch4_init },
14843};
Kailang Yangdf694da2005-12-05 19:42:22 +010014844
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014845/* Set mic1 and line-in as input and unmute the mixer */
14846static struct hda_verb alc861_asus_ch2_init[] = {
14847 /* set pin widget 1Ah (line in) for input */
14848 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014849 /* set pin widget 18h (mic1/2) for input, for mic also enable
14850 * the vref
14851 */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014852 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
14853
14854 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
14855#if 0
14856 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
14857 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
14858#endif
14859 { } /* end */
14860};
14861/* Set mic1 nad line-in as output and mute mixer */
14862static struct hda_verb alc861_asus_ch6_init[] = {
14863 /* set pin widget 1Ah (line in) for output (Back Surround)*/
14864 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14865 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
14866 /* set pin widget 18h (mic1) for output (CLFE)*/
14867 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
14868 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
14869 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
14870 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
14871
14872 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
14873#if 0
14874 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
14875 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
14876#endif
14877 { } /* end */
14878};
14879
14880static struct hda_channel_mode alc861_asus_modes[2] = {
14881 { 2, alc861_asus_ch2_init },
14882 { 6, alc861_asus_ch6_init },
14883};
14884
Kailang Yangdf694da2005-12-05 19:42:22 +010014885/* patch-ALC861 */
14886
14887static struct snd_kcontrol_new alc861_base_mixer[] = {
14888 /* output mixer control */
14889 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14890 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14891 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14892 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14893 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
14894
14895 /*Input mixer control */
14896 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14897 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14898 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14899 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14900 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14901 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14902 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14903 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14904 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14905 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014906
Kailang Yangdf694da2005-12-05 19:42:22 +010014907 { } /* end */
14908};
14909
14910static struct snd_kcontrol_new alc861_3ST_mixer[] = {
14911 /* output mixer control */
14912 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14913 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14914 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14915 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14916 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
14917
14918 /* Input mixer control */
14919 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14920 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14921 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14922 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14923 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14924 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14925 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14926 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14927 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14928 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014929
Kailang Yangdf694da2005-12-05 19:42:22 +010014930 {
14931 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14932 .name = "Channel Mode",
14933 .info = alc_ch_mode_info,
14934 .get = alc_ch_mode_get,
14935 .put = alc_ch_mode_put,
14936 .private_value = ARRAY_SIZE(alc861_threestack_modes),
14937 },
14938 { } /* end */
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014939};
14940
Takashi Iwaid1d985f2006-11-23 19:27:12 +010014941static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014942 /* output mixer control */
14943 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14944 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14945 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
Kailang Yangea1fb292008-08-26 12:58:38 +020014946
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014947 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014948};
Tobin Davisa53d1ae2006-10-17 12:00:28 +020014949
Takashi Iwai22309c32006-08-09 16:57:28 +020014950static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
14951 /* output mixer control */
14952 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14953 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14954 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14955 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14956 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
14957
14958 /* Input mixer control */
14959 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14960 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
14961 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14962 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14963 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14964 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14965 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14966 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14967 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
14968 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014969
Takashi Iwai22309c32006-08-09 16:57:28 +020014970 {
14971 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14972 .name = "Channel Mode",
14973 .info = alc_ch_mode_info,
14974 .get = alc_ch_mode_get,
14975 .put = alc_ch_mode_put,
14976 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
14977 },
14978 { } /* end */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014979};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020014980
14981static struct snd_kcontrol_new alc861_asus_mixer[] = {
14982 /* output mixer control */
14983 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
14984 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
14985 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
14986 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
14987 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
14988
14989 /* Input mixer control */
14990 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
14991 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
14992 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
14993 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
14994 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
14995 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
14996 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
14997 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
14998 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020014999 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
15000
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015001 {
15002 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
15003 .name = "Channel Mode",
15004 .info = alc_ch_mode_info,
15005 .get = alc_ch_mode_get,
15006 .put = alc_ch_mode_put,
15007 .private_value = ARRAY_SIZE(alc861_asus_modes),
15008 },
15009 { }
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010015010};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015011
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010015012/* additional mixer */
Takashi Iwaid1d985f2006-11-23 19:27:12 +010015013static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010015014 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
15015 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010015016 { }
15017};
15018
Kailang Yangdf694da2005-12-05 19:42:22 +010015019/*
15020 * generic initialization of ADC, input mixers and output mixers
15021 */
15022static struct hda_verb alc861_base_init_verbs[] = {
15023 /*
15024 * Unmute ADC0 and set the default input to mic-in
15025 */
15026 /* port-A for surround (rear panel) */
15027 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15028 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
15029 /* port-B for mic-in (rear panel) with vref */
15030 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15031 /* port-C for line-in (rear panel) */
15032 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15033 /* port-D for Front */
15034 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15035 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15036 /* port-E for HP out (front panel) */
15037 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
15038 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010015039 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010015040 /* port-F for mic-in (front panel) with vref */
15041 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15042 /* port-G for CLFE (rear panel) */
15043 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15044 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
15045 /* port-H for side (rear panel) */
15046 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15047 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
15048 /* CD-in */
15049 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15050 /* route front mic to ADC1*/
15051 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15052 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015053
Kailang Yangdf694da2005-12-05 19:42:22 +010015054 /* Unmute DAC0~3 & spdif out*/
15055 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15056 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15057 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15058 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15059 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020015060
Kailang Yangdf694da2005-12-05 19:42:22 +010015061 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15062 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15063 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15064 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15065 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015066
Kailang Yangdf694da2005-12-05 19:42:22 +010015067 /* Unmute Stereo Mixer 15 */
15068 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15069 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15070 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015071 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Kailang Yangdf694da2005-12-05 19:42:22 +010015072
15073 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15074 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15075 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15076 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15077 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15078 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15079 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15080 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015081 /* hp used DAC 3 (Front) */
15082 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010015083 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15084
15085 { }
15086};
15087
15088static struct hda_verb alc861_threestack_init_verbs[] = {
15089 /*
15090 * Unmute ADC0 and set the default input to mic-in
15091 */
15092 /* port-A for surround (rear panel) */
15093 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15094 /* port-B for mic-in (rear panel) with vref */
15095 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15096 /* port-C for line-in (rear panel) */
15097 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15098 /* port-D for Front */
15099 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15100 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15101 /* port-E for HP out (front panel) */
15102 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
15103 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010015104 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Kailang Yangdf694da2005-12-05 19:42:22 +010015105 /* port-F for mic-in (front panel) with vref */
15106 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15107 /* port-G for CLFE (rear panel) */
15108 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15109 /* port-H for side (rear panel) */
15110 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15111 /* CD-in */
15112 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15113 /* route front mic to ADC1*/
15114 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15115 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15116 /* Unmute DAC0~3 & spdif out*/
15117 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15118 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15119 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15120 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15121 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020015122
Kailang Yangdf694da2005-12-05 19:42:22 +010015123 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15124 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15125 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15126 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15127 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015128
Kailang Yangdf694da2005-12-05 19:42:22 +010015129 /* Unmute Stereo Mixer 15 */
15130 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15131 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15132 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015133 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Kailang Yangdf694da2005-12-05 19:42:22 +010015134
15135 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15136 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15137 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15138 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15139 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15140 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15141 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15142 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015143 /* hp used DAC 3 (Front) */
15144 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010015145 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15146 { }
15147};
Takashi Iwai22309c32006-08-09 16:57:28 +020015148
15149static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
15150 /*
15151 * Unmute ADC0 and set the default input to mic-in
15152 */
15153 /* port-A for surround (rear panel) */
15154 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15155 /* port-B for mic-in (rear panel) with vref */
15156 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15157 /* port-C for line-in (rear panel) */
15158 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15159 /* port-D for Front */
15160 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15161 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15162 /* port-E for HP out (front panel) */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015163 /* this has to be set to VREF80 */
15164 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
Takashi Iwai22309c32006-08-09 16:57:28 +020015165 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010015166 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Takashi Iwai22309c32006-08-09 16:57:28 +020015167 /* port-F for mic-in (front panel) with vref */
15168 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15169 /* port-G for CLFE (rear panel) */
15170 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15171 /* port-H for side (rear panel) */
15172 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15173 /* CD-in */
15174 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15175 /* route front mic to ADC1*/
15176 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15177 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15178 /* Unmute DAC0~3 & spdif out*/
15179 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15180 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15181 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15182 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15183 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020015184
Takashi Iwai22309c32006-08-09 16:57:28 +020015185 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15186 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15187 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15188 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15189 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015190
Takashi Iwai22309c32006-08-09 16:57:28 +020015191 /* Unmute Stereo Mixer 15 */
15192 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15193 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15194 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015195 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Takashi Iwai22309c32006-08-09 16:57:28 +020015196
15197 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15198 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15199 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15200 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15201 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15202 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15203 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15204 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015205 /* hp used DAC 3 (Front) */
15206 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Takashi Iwai22309c32006-08-09 16:57:28 +020015207 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15208 { }
15209};
15210
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015211static struct hda_verb alc861_asus_init_verbs[] = {
15212 /*
15213 * Unmute ADC0 and set the default input to mic-in
15214 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015215 /* port-A for surround (rear panel)
15216 * according to codec#0 this is the HP jack
15217 */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015218 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
15219 /* route front PCM to HP */
15220 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
15221 /* port-B for mic-in (rear panel) with vref */
15222 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15223 /* port-C for line-in (rear panel) */
15224 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15225 /* port-D for Front */
15226 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15227 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
15228 /* port-E for HP out (front panel) */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015229 /* this has to be set to VREF80 */
15230 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015231 /* route front PCM to HP */
Takashi Iwai9dece1d2006-11-16 17:12:49 +010015232 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015233 /* port-F for mic-in (front panel) with vref */
15234 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
15235 /* port-G for CLFE (rear panel) */
15236 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15237 /* port-H for side (rear panel) */
15238 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
15239 /* CD-in */
15240 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
15241 /* route front mic to ADC1*/
15242 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
15243 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15244 /* Unmute DAC0~3 & spdif out*/
15245 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15246 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15247 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15248 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15249 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
15250 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15251 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15252 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15253 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15254 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015255
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015256 /* Unmute Stereo Mixer 15 */
15257 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15258 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15259 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015260 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015261
15262 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15263 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15264 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15265 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15266 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15267 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15268 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15269 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015270 /* hp used DAC 3 (Front) */
15271 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015272 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15273 { }
15274};
15275
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010015276/* additional init verbs for ASUS laptops */
15277static struct hda_verb alc861_asus_laptop_init_verbs[] = {
15278 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
15279 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
15280 { }
15281};
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015282
Kailang Yangdf694da2005-12-05 19:42:22 +010015283/*
15284 * generic initialization of ADC, input mixers and output mixers
15285 */
15286static struct hda_verb alc861_auto_init_verbs[] = {
15287 /*
15288 * Unmute ADC0 and set the default input to mic-in
15289 */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015290 /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
Kailang Yangdf694da2005-12-05 19:42:22 +010015291 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015292
Kailang Yangdf694da2005-12-05 19:42:22 +010015293 /* Unmute DAC0~3 & spdif out*/
15294 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15295 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15296 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15297 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
15298 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangea1fb292008-08-26 12:58:38 +020015299
Kailang Yangdf694da2005-12-05 19:42:22 +010015300 /* Unmute Mixer 14 (mic) 1c (Line in)*/
15301 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15302 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15303 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15304 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020015305
Kailang Yangdf694da2005-12-05 19:42:22 +010015306 /* Unmute Stereo Mixer 15 */
15307 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
15308 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
15309 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
15310 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
15311
Takashi Iwai1c209302009-07-22 15:17:45 +020015312 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15313 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15314 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15315 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15316 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15317 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
15318 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15319 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yangdf694da2005-12-05 19:42:22 +010015320
15321 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15322 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai1c209302009-07-22 15:17:45 +020015323 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15324 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010015325 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
15326 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Takashi Iwai1c209302009-07-22 15:17:45 +020015327 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
15328 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
Kailang Yangdf694da2005-12-05 19:42:22 +010015329
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015330 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */
Kailang Yangdf694da2005-12-05 19:42:22 +010015331
15332 { }
15333};
15334
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015335static struct hda_verb alc861_toshiba_init_verbs[] = {
15336 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015337
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015338 { }
15339};
15340
15341/* toggle speaker-output according to the hp-jack state */
15342static void alc861_toshiba_automute(struct hda_codec *codec)
15343{
Wu Fengguang864f92b2009-11-18 12:38:02 +080015344 unsigned int present = snd_hda_jack_detect(codec, 0x0f);
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015345
Takashi Iwai47fd8302007-08-10 17:11:07 +020015346 snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
15347 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
15348 snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
15349 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015350}
15351
15352static void alc861_toshiba_unsol_event(struct hda_codec *codec,
15353 unsigned int res)
15354{
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015355 if ((res >> 26) == ALC880_HP_EVENT)
15356 alc861_toshiba_automute(codec);
15357}
15358
Sasha Alexandrdef319f2009-06-16 16:00:15 -040015359/* pcm configuration: identical with ALC880 */
Kailang Yangdf694da2005-12-05 19:42:22 +010015360#define alc861_pcm_analog_playback alc880_pcm_analog_playback
15361#define alc861_pcm_analog_capture alc880_pcm_analog_capture
15362#define alc861_pcm_digital_playback alc880_pcm_digital_playback
15363#define alc861_pcm_digital_capture alc880_pcm_digital_capture
15364
15365
15366#define ALC861_DIGOUT_NID 0x07
15367
15368static struct hda_channel_mode alc861_8ch_modes[1] = {
15369 { 8, NULL }
15370};
15371
15372static hda_nid_t alc861_dac_nids[4] = {
15373 /* front, surround, clfe, side */
15374 0x03, 0x06, 0x05, 0x04
15375};
15376
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015377static hda_nid_t alc660_dac_nids[3] = {
15378 /* front, clfe, surround */
15379 0x03, 0x05, 0x06
15380};
15381
Kailang Yangdf694da2005-12-05 19:42:22 +010015382static hda_nid_t alc861_adc_nids[1] = {
15383 /* ADC0-2 */
15384 0x08,
15385};
15386
15387static struct hda_input_mux alc861_capture_source = {
15388 .num_items = 5,
15389 .items = {
15390 { "Mic", 0x0 },
15391 { "Front Mic", 0x3 },
15392 { "Line", 0x1 },
15393 { "CD", 0x4 },
15394 { "Mixer", 0x5 },
15395 },
15396};
15397
Takashi Iwai1c209302009-07-22 15:17:45 +020015398static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
15399{
15400 struct alc_spec *spec = codec->spec;
15401 hda_nid_t mix, srcs[5];
15402 int i, j, num;
15403
15404 if (snd_hda_get_connections(codec, pin, &mix, 1) != 1)
15405 return 0;
15406 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
15407 if (num < 0)
15408 return 0;
15409 for (i = 0; i < num; i++) {
15410 unsigned int type;
Takashi Iwaia22d5432009-07-27 12:54:26 +020015411 type = get_wcaps_type(get_wcaps(codec, srcs[i]));
Takashi Iwai1c209302009-07-22 15:17:45 +020015412 if (type != AC_WID_AUD_OUT)
15413 continue;
15414 for (j = 0; j < spec->multiout.num_dacs; j++)
15415 if (spec->multiout.dac_nids[j] == srcs[i])
15416 break;
15417 if (j >= spec->multiout.num_dacs)
15418 return srcs[i];
15419 }
15420 return 0;
15421}
15422
Kailang Yangdf694da2005-12-05 19:42:22 +010015423/* fill in the dac_nids table from the parsed pin configuration */
Takashi Iwai1c209302009-07-22 15:17:45 +020015424static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015425 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010015426{
Takashi Iwai1c209302009-07-22 15:17:45 +020015427 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015428 int i;
Takashi Iwai1c209302009-07-22 15:17:45 +020015429 hda_nid_t nid, dac;
Kailang Yangdf694da2005-12-05 19:42:22 +010015430
15431 spec->multiout.dac_nids = spec->private_dac_nids;
15432 for (i = 0; i < cfg->line_outs; i++) {
15433 nid = cfg->line_out_pins[i];
Takashi Iwai1c209302009-07-22 15:17:45 +020015434 dac = alc861_look_for_dac(codec, nid);
15435 if (!dac)
15436 continue;
15437 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
Kailang Yangdf694da2005-12-05 19:42:22 +010015438 }
Kailang Yangdf694da2005-12-05 19:42:22 +010015439 return 0;
15440}
15441
Takashi Iwai1c209302009-07-22 15:17:45 +020015442static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
15443 hda_nid_t nid, unsigned int chs)
Kailang Yangdf694da2005-12-05 19:42:22 +010015444{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020015445 return add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai1c209302009-07-22 15:17:45 +020015446 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
15447}
15448
15449/* add playback controls from the parsed DAC table */
15450static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
15451 const struct auto_pin_cfg *cfg)
15452{
15453 struct alc_spec *spec = codec->spec;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015454 static const char *chname[4] = {
15455 "Front", "Surround", NULL /*CLFE*/, "Side"
15456 };
Kailang Yangdf694da2005-12-05 19:42:22 +010015457 hda_nid_t nid;
Takashi Iwai1c209302009-07-22 15:17:45 +020015458 int i, err;
15459
15460 if (cfg->line_outs == 1) {
15461 const char *pfx = NULL;
15462 if (!cfg->hp_outs)
15463 pfx = "Master";
15464 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
15465 pfx = "Speaker";
15466 if (pfx) {
15467 nid = spec->multiout.dac_nids[0];
15468 return alc861_create_out_sw(codec, pfx, nid, 3);
15469 }
15470 }
Kailang Yangdf694da2005-12-05 19:42:22 +010015471
15472 for (i = 0; i < cfg->line_outs; i++) {
15473 nid = spec->multiout.dac_nids[i];
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015474 if (!nid)
Kailang Yangdf694da2005-12-05 19:42:22 +010015475 continue;
Takashi Iwai1c209302009-07-22 15:17:45 +020015476 if (i == 2) {
Kailang Yangdf694da2005-12-05 19:42:22 +010015477 /* Center/LFE */
Takashi Iwai1c209302009-07-22 15:17:45 +020015478 err = alc861_create_out_sw(codec, "Center", nid, 1);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015479 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015480 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020015481 err = alc861_create_out_sw(codec, "LFE", nid, 2);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015482 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015483 return err;
15484 } else {
Takashi Iwai1c209302009-07-22 15:17:45 +020015485 err = alc861_create_out_sw(codec, chname[i], nid, 3);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015486 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015487 return err;
15488 }
15489 }
15490 return 0;
15491}
15492
Takashi Iwai1c209302009-07-22 15:17:45 +020015493static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
Kailang Yangdf694da2005-12-05 19:42:22 +010015494{
Takashi Iwai1c209302009-07-22 15:17:45 +020015495 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015496 int err;
15497 hda_nid_t nid;
15498
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015499 if (!pin)
Kailang Yangdf694da2005-12-05 19:42:22 +010015500 return 0;
15501
15502 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
Takashi Iwai1c209302009-07-22 15:17:45 +020015503 nid = alc861_look_for_dac(codec, pin);
15504 if (nid) {
15505 err = alc861_create_out_sw(codec, "Headphone", nid, 3);
15506 if (err < 0)
15507 return err;
15508 spec->multiout.hp_nid = nid;
15509 }
Kailang Yangdf694da2005-12-05 19:42:22 +010015510 }
15511 return 0;
15512}
15513
15514/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020015515static int alc861_auto_create_input_ctls(struct hda_codec *codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015516 const struct auto_pin_cfg *cfg)
Kailang Yangdf694da2005-12-05 19:42:22 +010015517{
Takashi Iwai05f5f472009-08-25 13:10:18 +020015518 return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x08, 0);
Kailang Yangdf694da2005-12-05 19:42:22 +010015519}
15520
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015521static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
15522 hda_nid_t nid,
Takashi Iwai1c209302009-07-22 15:17:45 +020015523 int pin_type, hda_nid_t dac)
Kailang Yangdf694da2005-12-05 19:42:22 +010015524{
Takashi Iwai1c209302009-07-22 15:17:45 +020015525 hda_nid_t mix, srcs[5];
15526 int i, num;
15527
Jacek Luczak564c5be2008-05-03 18:41:23 +020015528 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
15529 pin_type);
Takashi Iwai1c209302009-07-22 15:17:45 +020015530 snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
Jacek Luczak564c5be2008-05-03 18:41:23 +020015531 AMP_OUT_UNMUTE);
Takashi Iwai1c209302009-07-22 15:17:45 +020015532 if (snd_hda_get_connections(codec, nid, &mix, 1) != 1)
15533 return;
15534 num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
15535 if (num < 0)
15536 return;
15537 for (i = 0; i < num; i++) {
15538 unsigned int mute;
15539 if (srcs[i] == dac || srcs[i] == 0x15)
15540 mute = AMP_IN_UNMUTE(i);
15541 else
15542 mute = AMP_IN_MUTE(i);
15543 snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
15544 mute);
15545 }
Kailang Yangdf694da2005-12-05 19:42:22 +010015546}
15547
15548static void alc861_auto_init_multi_out(struct hda_codec *codec)
15549{
15550 struct alc_spec *spec = codec->spec;
15551 int i;
15552
15553 for (i = 0; i < spec->autocfg.line_outs; i++) {
15554 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020015555 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangdf694da2005-12-05 19:42:22 +010015556 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020015557 alc861_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015558 spec->multiout.dac_nids[i]);
Kailang Yangdf694da2005-12-05 19:42:22 +010015559 }
15560}
15561
15562static void alc861_auto_init_hp_out(struct hda_codec *codec)
15563{
15564 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015565
Takashi Iwai15870f02009-10-05 08:25:13 +020015566 if (spec->autocfg.hp_outs)
15567 alc861_auto_set_output_and_unmute(codec,
15568 spec->autocfg.hp_pins[0],
15569 PIN_HP,
Takashi Iwai1c209302009-07-22 15:17:45 +020015570 spec->multiout.hp_nid);
Takashi Iwai15870f02009-10-05 08:25:13 +020015571 if (spec->autocfg.speaker_outs)
15572 alc861_auto_set_output_and_unmute(codec,
15573 spec->autocfg.speaker_pins[0],
15574 PIN_OUT,
Takashi Iwai1c209302009-07-22 15:17:45 +020015575 spec->multiout.dac_nids[0]);
Kailang Yangdf694da2005-12-05 19:42:22 +010015576}
15577
15578static void alc861_auto_init_analog_input(struct hda_codec *codec)
15579{
15580 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +020015581 struct auto_pin_cfg *cfg = &spec->autocfg;
Kailang Yangdf694da2005-12-05 19:42:22 +010015582 int i;
15583
Takashi Iwai66ceeb62010-08-30 13:05:52 +020015584 for (i = 0; i < cfg->num_inputs; i++) {
15585 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai23f0c042009-02-26 13:03:58 +010015586 if (nid >= 0x0c && nid <= 0x11)
15587 alc_set_input_pin(codec, nid, i);
Kailang Yangdf694da2005-12-05 19:42:22 +010015588 }
15589}
15590
15591/* parse the BIOS configuration and set up the alc_spec */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015592/* return 1 if successful, 0 if the proper config is not found,
15593 * or a negative error code
15594 */
Kailang Yangdf694da2005-12-05 19:42:22 +010015595static int alc861_parse_auto_config(struct hda_codec *codec)
15596{
15597 struct alc_spec *spec = codec->spec;
15598 int err;
15599 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
15600
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015601 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
15602 alc861_ignore);
15603 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015604 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015605 if (!spec->autocfg.line_outs)
Kailang Yangdf694da2005-12-05 19:42:22 +010015606 return 0; /* can't find valid BIOS pin config */
15607
Takashi Iwai1c209302009-07-22 15:17:45 +020015608 err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015609 if (err < 0)
15610 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020015611 err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015612 if (err < 0)
15613 return err;
Takashi Iwai1c209302009-07-22 15:17:45 +020015614 err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015615 if (err < 0)
15616 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020015617 err = alc861_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015618 if (err < 0)
Kailang Yangdf694da2005-12-05 19:42:22 +010015619 return err;
15620
15621 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
15622
Takashi Iwai757899a2010-07-30 10:48:14 +020015623 alc_auto_parse_digital(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010015624
Takashi Iwai603c4012008-07-30 15:01:44 +020015625 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010015626 add_mixer(spec, spec->kctls.list);
Kailang Yangdf694da2005-12-05 19:42:22 +010015627
Takashi Iwaid88897e2008-10-31 15:01:37 +010015628 add_verb(spec, alc861_auto_init_verbs);
Kailang Yangdf694da2005-12-05 19:42:22 +010015629
Jonathan Woithea1e8d2d2006-03-28 12:47:09 +020015630 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020015631 spec->input_mux = &spec->private_imux[0];
Kailang Yangdf694da2005-12-05 19:42:22 +010015632
15633 spec->adc_nids = alc861_adc_nids;
15634 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
Takashi Iwaib59bdf32009-08-11 09:47:30 +020015635 set_capture_mixer(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010015636
Kailang Yang6227cdc2010-02-25 08:36:52 +010015637 alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020015638
Kailang Yangdf694da2005-12-05 19:42:22 +010015639 return 1;
15640}
15641
Takashi Iwaiae6b8132006-03-03 16:47:17 +010015642/* additional initialization for auto-configuration model */
15643static void alc861_auto_init(struct hda_codec *codec)
Kailang Yangdf694da2005-12-05 19:42:22 +010015644{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010015645 struct alc_spec *spec = codec->spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015646 alc861_auto_init_multi_out(codec);
15647 alc861_auto_init_hp_out(codec);
15648 alc861_auto_init_analog_input(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +020015649 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010015650 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020015651 alc_inithook(codec);
Kailang Yangdf694da2005-12-05 19:42:22 +010015652}
15653
Takashi Iwaicb53c622007-08-10 17:21:45 +020015654#ifdef CONFIG_SND_HDA_POWER_SAVE
15655static struct hda_amp_list alc861_loopbacks[] = {
15656 { 0x15, HDA_INPUT, 0 },
15657 { 0x15, HDA_INPUT, 1 },
15658 { 0x15, HDA_INPUT, 2 },
15659 { 0x15, HDA_INPUT, 3 },
15660 { } /* end */
15661};
15662#endif
15663
Kailang Yangdf694da2005-12-05 19:42:22 +010015664
15665/*
15666 * configuration and preset
15667 */
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015668static const char *alc861_models[ALC861_MODEL_LAST] = {
15669 [ALC861_3ST] = "3stack",
15670 [ALC660_3ST] = "3stack-660",
15671 [ALC861_3ST_DIG] = "3stack-dig",
15672 [ALC861_6ST_DIG] = "6stack-dig",
15673 [ALC861_UNIWILL_M31] = "uniwill-m31",
15674 [ALC861_TOSHIBA] = "toshiba",
15675 [ALC861_ASUS] = "asus",
15676 [ALC861_ASUS_LAPTOP] = "asus-laptop",
15677 [ALC861_AUTO] = "auto",
15678};
15679
15680static struct snd_pci_quirk alc861_cfg_tbl[] = {
Takashi Iwai687a47b2007-01-10 11:25:58 +010015681 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015682 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
15683 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
15684 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015685 SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
Kailang Yang83c34212007-07-05 11:43:05 +020015686 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
Tobin Davisad5e7732007-01-08 10:57:32 +010015687 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
Takashi Iwai341d4eb2007-07-09 17:53:18 +020015688 /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
15689 * Any other models that need this preset?
15690 */
15691 /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
Claudio Matsuokaef64adb2007-07-14 00:26:16 +020015692 SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
15693 SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010015694 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
15695 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
15696 SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
15697 /* FIXME: the below seems conflict */
15698 /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
15699 SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
15700 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
Kailang Yangdf694da2005-12-05 19:42:22 +010015701 {}
15702};
15703
15704static struct alc_config_preset alc861_presets[] = {
15705 [ALC861_3ST] = {
15706 .mixers = { alc861_3ST_mixer },
15707 .init_verbs = { alc861_threestack_init_verbs },
15708 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15709 .dac_nids = alc861_dac_nids,
15710 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15711 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015712 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +010015713 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15714 .adc_nids = alc861_adc_nids,
15715 .input_mux = &alc861_capture_source,
15716 },
15717 [ALC861_3ST_DIG] = {
15718 .mixers = { alc861_base_mixer },
15719 .init_verbs = { alc861_threestack_init_verbs },
15720 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15721 .dac_nids = alc861_dac_nids,
15722 .dig_out_nid = ALC861_DIGOUT_NID,
15723 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15724 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015725 .need_dac_fix = 1,
Kailang Yangdf694da2005-12-05 19:42:22 +010015726 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15727 .adc_nids = alc861_adc_nids,
15728 .input_mux = &alc861_capture_source,
15729 },
15730 [ALC861_6ST_DIG] = {
15731 .mixers = { alc861_base_mixer },
15732 .init_verbs = { alc861_base_init_verbs },
15733 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15734 .dac_nids = alc861_dac_nids,
15735 .dig_out_nid = ALC861_DIGOUT_NID,
15736 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
15737 .channel_mode = alc861_8ch_modes,
15738 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15739 .adc_nids = alc861_adc_nids,
15740 .input_mux = &alc861_capture_source,
15741 },
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015742 [ALC660_3ST] = {
15743 .mixers = { alc861_3ST_mixer },
15744 .init_verbs = { alc861_threestack_init_verbs },
15745 .num_dacs = ARRAY_SIZE(alc660_dac_nids),
15746 .dac_nids = alc660_dac_nids,
15747 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
15748 .channel_mode = alc861_threestack_modes,
Takashi Iwai4e195a72006-07-28 14:47:34 +020015749 .need_dac_fix = 1,
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015750 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15751 .adc_nids = alc861_adc_nids,
15752 .input_mux = &alc861_capture_source,
15753 },
Takashi Iwai22309c32006-08-09 16:57:28 +020015754 [ALC861_UNIWILL_M31] = {
15755 .mixers = { alc861_uniwill_m31_mixer },
15756 .init_verbs = { alc861_uniwill_m31_init_verbs },
15757 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15758 .dac_nids = alc861_dac_nids,
15759 .dig_out_nid = ALC861_DIGOUT_NID,
15760 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
15761 .channel_mode = alc861_uniwill_m31_modes,
15762 .need_dac_fix = 1,
15763 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15764 .adc_nids = alc861_adc_nids,
15765 .input_mux = &alc861_capture_source,
15766 },
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015767 [ALC861_TOSHIBA] = {
15768 .mixers = { alc861_toshiba_mixer },
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015769 .init_verbs = { alc861_base_init_verbs,
15770 alc861_toshiba_init_verbs },
Tobin Davisa53d1ae2006-10-17 12:00:28 +020015771 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15772 .dac_nids = alc861_dac_nids,
15773 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
15774 .channel_mode = alc883_3ST_2ch_modes,
15775 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15776 .adc_nids = alc861_adc_nids,
15777 .input_mux = &alc861_capture_source,
15778 .unsol_event = alc861_toshiba_unsol_event,
15779 .init_hook = alc861_toshiba_automute,
15780 },
Mariusz Domanski7cdbff92006-10-23 13:42:56 +020015781 [ALC861_ASUS] = {
15782 .mixers = { alc861_asus_mixer },
15783 .init_verbs = { alc861_asus_init_verbs },
15784 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15785 .dac_nids = alc861_dac_nids,
15786 .dig_out_nid = ALC861_DIGOUT_NID,
15787 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
15788 .channel_mode = alc861_asus_modes,
15789 .need_dac_fix = 1,
15790 .hp_nid = 0x06,
15791 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15792 .adc_nids = alc861_adc_nids,
15793 .input_mux = &alc861_capture_source,
15794 },
Takashi Iwai56bb0ca2006-11-22 11:52:52 +010015795 [ALC861_ASUS_LAPTOP] = {
15796 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
15797 .init_verbs = { alc861_asus_init_verbs,
15798 alc861_asus_laptop_init_verbs },
15799 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
15800 .dac_nids = alc861_dac_nids,
15801 .dig_out_nid = ALC861_DIGOUT_NID,
15802 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
15803 .channel_mode = alc883_3ST_2ch_modes,
15804 .need_dac_fix = 1,
15805 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
15806 .adc_nids = alc861_adc_nids,
15807 .input_mux = &alc861_capture_source,
15808 },
15809};
Kailang Yangdf694da2005-12-05 19:42:22 +010015810
Takashi Iwaicfc9b062009-12-01 12:19:37 +010015811/* Pin config fixes */
15812enum {
15813 PINFIX_FSC_AMILO_PI1505,
15814};
15815
Takashi Iwaicfc9b062009-12-01 12:19:37 +010015816static const struct alc_fixup alc861_fixups[] = {
15817 [PINFIX_FSC_AMILO_PI1505] = {
Takashi Iwai73413b12010-08-30 09:39:57 +020015818 .pins = (const struct alc_pincfg[]) {
15819 { 0x0b, 0x0221101f }, /* HP */
15820 { 0x0f, 0x90170310 }, /* speaker */
15821 { }
15822 }
Takashi Iwaicfc9b062009-12-01 12:19:37 +010015823 },
15824};
15825
15826static struct snd_pci_quirk alc861_fixup_tbl[] = {
15827 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
15828 {}
15829};
Kailang Yangdf694da2005-12-05 19:42:22 +010015830
15831static int patch_alc861(struct hda_codec *codec)
15832{
15833 struct alc_spec *spec;
15834 int board_config;
15835 int err;
15836
Robert P. J. Daydc041e02006-12-19 14:44:15 +010015837 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Kailang Yangdf694da2005-12-05 19:42:22 +010015838 if (spec == NULL)
15839 return -ENOMEM;
15840
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015841 codec->spec = spec;
Kailang Yangdf694da2005-12-05 19:42:22 +010015842
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015843 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
15844 alc861_models,
15845 alc861_cfg_tbl);
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015846
Takashi Iwaif5fcc132006-11-24 17:07:44 +010015847 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020015848 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
15849 codec->chip_name);
Kailang Yangdf694da2005-12-05 19:42:22 +010015850 board_config = ALC861_AUTO;
15851 }
15852
Takashi Iwai7fa90e82010-04-12 08:49:00 +020015853 if (board_config == ALC861_AUTO)
15854 alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 1);
Takashi Iwaicfc9b062009-12-01 12:19:37 +010015855
Kailang Yangdf694da2005-12-05 19:42:22 +010015856 if (board_config == ALC861_AUTO) {
15857 /* automatic parse from the BIOS config */
15858 err = alc861_parse_auto_config(codec);
15859 if (err < 0) {
15860 alc_free(codec);
15861 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020015862 } else if (!err) {
Takashi Iwai9c7f8522006-06-28 15:08:22 +020015863 printk(KERN_INFO
15864 "hda_codec: Cannot set up configuration "
15865 "from BIOS. Using base mode...\n");
Kailang Yangdf694da2005-12-05 19:42:22 +010015866 board_config = ALC861_3ST_DIG;
15867 }
15868 }
15869
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090015870 err = snd_hda_attach_beep_device(codec, 0x23);
15871 if (err < 0) {
15872 alc_free(codec);
15873 return err;
15874 }
15875
Kailang Yangdf694da2005-12-05 19:42:22 +010015876 if (board_config != ALC861_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020015877 setup_preset(codec, &alc861_presets[board_config]);
Kailang Yangdf694da2005-12-05 19:42:22 +010015878
Kailang Yangdf694da2005-12-05 19:42:22 +010015879 spec->stream_analog_playback = &alc861_pcm_analog_playback;
15880 spec->stream_analog_capture = &alc861_pcm_analog_capture;
15881
Kailang Yangdf694da2005-12-05 19:42:22 +010015882 spec->stream_digital_playback = &alc861_pcm_digital_playback;
15883 spec->stream_digital_capture = &alc861_pcm_digital_capture;
15884
Takashi Iwaic7a8eb12010-01-14 12:39:02 +010015885 if (!spec->cap_mixer)
15886 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010015887 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
15888
Takashi Iwai2134ea42008-01-10 16:53:55 +010015889 spec->vmaster_nid = 0x03;
15890
Takashi Iwai7fa90e82010-04-12 08:49:00 +020015891 if (board_config == ALC861_AUTO)
15892 alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 0);
15893
Kailang Yangdf694da2005-12-05 19:42:22 +010015894 codec->patch_ops = alc_patch_ops;
Daniel T Chenc97259d2009-12-27 18:52:08 -050015895 if (board_config == ALC861_AUTO) {
Takashi Iwaiae6b8132006-03-03 16:47:17 +010015896 spec->init_hook = alc861_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020015897#ifdef CONFIG_SND_HDA_POWER_SAVE
Daniel T Chenc97259d2009-12-27 18:52:08 -050015898 spec->power_hook = alc_power_eapd;
15899#endif
15900 }
15901#ifdef CONFIG_SND_HDA_POWER_SAVE
Takashi Iwaicb53c622007-08-10 17:21:45 +020015902 if (!spec->loopback.amplist)
15903 spec->loopback.amplist = alc861_loopbacks;
15904#endif
Kailang Yangea1fb292008-08-26 12:58:38 +020015905
Kailang Yangdf694da2005-12-05 19:42:22 +010015906 return 0;
15907}
15908
15909/*
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015910 * ALC861-VD support
15911 *
15912 * Based on ALC882
15913 *
15914 * In addition, an independent DAC
15915 */
15916#define ALC861VD_DIGOUT_NID 0x06
15917
15918static hda_nid_t alc861vd_dac_nids[4] = {
15919 /* front, surr, clfe, side surr */
15920 0x02, 0x03, 0x04, 0x05
15921};
15922
15923/* dac_nids for ALC660vd are in a different order - according to
15924 * Realtek's driver.
Sasha Alexandrdef319f2009-06-16 16:00:15 -040015925 * This should probably result in a different mixer for 6stack models
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015926 * of ALC660vd codecs, but for now there is only 3stack mixer
15927 * - and it is the same as in 861vd.
15928 * adc_nids in ALC660vd are (is) the same as in 861vd
15929 */
15930static hda_nid_t alc660vd_dac_nids[3] = {
15931 /* front, rear, clfe, rear_surr */
15932 0x02, 0x04, 0x03
15933};
15934
15935static hda_nid_t alc861vd_adc_nids[1] = {
15936 /* ADC0 */
15937 0x09,
15938};
15939
Takashi Iwaie1406342008-02-11 18:32:32 +010015940static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
15941
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015942/* input MUX */
15943/* FIXME: should be a matrix-type input source selection */
15944static struct hda_input_mux alc861vd_capture_source = {
15945 .num_items = 4,
15946 .items = {
15947 { "Mic", 0x0 },
15948 { "Front Mic", 0x1 },
15949 { "Line", 0x2 },
15950 { "CD", 0x4 },
15951 },
15952};
15953
Kailang Yang272a5272007-05-14 11:00:38 +020015954static struct hda_input_mux alc861vd_dallas_capture_source = {
Tobin Davisb419f342008-03-07 11:57:51 +010015955 .num_items = 2,
Kailang Yang272a5272007-05-14 11:00:38 +020015956 .items = {
Tobin Davisb419f342008-03-07 11:57:51 +010015957 { "Ext Mic", 0x0 },
15958 { "Int Mic", 0x1 },
Kailang Yang272a5272007-05-14 11:00:38 +020015959 },
15960};
15961
Kailang Yangd1a991a2007-08-15 16:21:59 +020015962static struct hda_input_mux alc861vd_hp_capture_source = {
15963 .num_items = 2,
15964 .items = {
15965 { "Front Mic", 0x0 },
15966 { "ATAPI Mic", 0x1 },
15967 },
15968};
15969
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010015970/*
15971 * 2ch mode
15972 */
15973static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
15974 { 2, NULL }
15975};
15976
15977/*
15978 * 6ch mode
15979 */
15980static struct hda_verb alc861vd_6stack_ch6_init[] = {
15981 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
15982 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15983 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15984 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15985 { } /* end */
15986};
15987
15988/*
15989 * 8ch mode
15990 */
15991static struct hda_verb alc861vd_6stack_ch8_init[] = {
15992 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15993 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15994 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15995 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
15996 { } /* end */
15997};
15998
15999static struct hda_channel_mode alc861vd_6stack_modes[2] = {
16000 { 6, alc861vd_6stack_ch6_init },
16001 { 8, alc861vd_6stack_ch8_init },
16002};
16003
16004static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
16005 {
16006 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
16007 .name = "Channel Mode",
16008 .info = alc_ch_mode_info,
16009 .get = alc_ch_mode_get,
16010 .put = alc_ch_mode_put,
16011 },
16012 { } /* end */
16013};
16014
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016015/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
16016 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
16017 */
16018static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
16019 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16020 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16021
16022 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16023 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
16024
16025 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
16026 HDA_OUTPUT),
16027 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
16028 HDA_OUTPUT),
16029 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
16030 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
16031
16032 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
16033 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
16034
16035 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16036
16037 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
16038 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16039 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16040
16041 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
16042 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16043 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16044
16045 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16046 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16047
16048 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16049 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16050
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016051 { } /* end */
16052};
16053
16054static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
16055 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16056 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16057
16058 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16059
16060 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
16061 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16062 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16063
16064 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
16065 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16066 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16067
16068 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
16069 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
16070
16071 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16072 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16073
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016074 { } /* end */
16075};
16076
Kailang Yangbdd148a2007-05-08 15:19:08 +020016077static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
16078 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16079 /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
16080 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
16081
16082 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
16083
16084 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
16085 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16086 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16087
16088 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
16089 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16090 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
16091
16092 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
16093 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
16094
16095 { } /* end */
16096};
16097
Tobin Davisb419f342008-03-07 11:57:51 +010016098/* Pin assignment: Speaker=0x14, HP = 0x15,
16099 * Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
Kailang Yang272a5272007-05-14 11:00:38 +020016100 */
16101static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
Tobin Davisb419f342008-03-07 11:57:51 +010016102 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16103 HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +020016104 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16105 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
Tobin Davisb419f342008-03-07 11:57:51 +010016106 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
16107 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16108 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16109 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
16110 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16111 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yang272a5272007-05-14 11:00:38 +020016112 { } /* end */
16113};
16114
Kailang Yangd1a991a2007-08-15 16:21:59 +020016115/* Pin assignment: Speaker=0x14, Line-out = 0x15,
16116 * Front Mic=0x18, ATAPI Mic = 0x19,
16117 */
16118static struct snd_kcontrol_new alc861vd_hp_mixer[] = {
16119 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
16120 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
16121 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
16122 HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
16123 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
16124 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
16125 HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
16126 HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangea1fb292008-08-26 12:58:38 +020016127
Kailang Yangd1a991a2007-08-15 16:21:59 +020016128 { } /* end */
16129};
16130
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016131/*
16132 * generic initialization of ADC, input mixers and output mixers
16133 */
16134static struct hda_verb alc861vd_volume_init_verbs[] = {
16135 /*
16136 * Unmute ADC0 and set the default input to mic-in
16137 */
16138 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
16139 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16140
16141 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
16142 * the analog-loopback mixer widget
16143 */
16144 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
Takashi Iwaicb53c622007-08-10 17:21:45 +020016145 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16146 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16147 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
16148 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
16149 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016150
16151 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
Kailang Yangbdd148a2007-05-08 15:19:08 +020016152 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16153 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16154 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016155 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016156
16157 /*
16158 * Set up output mixers (0x02 - 0x05)
16159 */
16160 /* set vol=0 to output mixers */
16161 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16162 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16163 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16164 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16165
16166 /* set up input amps for analog loopback */
16167 /* Amp Indices: DAC = 0, mixer = 1 */
16168 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16169 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16170 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16171 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16172 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16173 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16174 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16175 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16176
16177 { }
16178};
16179
16180/*
16181 * 3-stack pin configuration:
16182 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
16183 */
16184static struct hda_verb alc861vd_3stack_init_verbs[] = {
16185 /*
16186 * Set pin mode and muting
16187 */
16188 /* set front pin widgets 0x14 for output */
16189 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16190 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16191 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
16192
16193 /* Mic (rear) pin: input vref at 80% */
16194 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16195 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16196 /* Front Mic pin: input vref at 80% */
16197 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16198 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16199 /* Line In pin: input */
16200 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16201 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16202 /* Line-2 In: Headphone output (output 0 - 0x0c) */
16203 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16204 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16205 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
16206 /* CD pin widget for input */
16207 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16208
16209 { }
16210};
16211
16212/*
16213 * 6-stack pin configuration:
16214 */
16215static struct hda_verb alc861vd_6stack_init_verbs[] = {
16216 /*
16217 * Set pin mode and muting
16218 */
16219 /* set front pin widgets 0x14 for output */
16220 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16221 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16222 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
16223
16224 /* Rear Pin: output 1 (0x0d) */
16225 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16226 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16227 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
16228 /* CLFE Pin: output 2 (0x0e) */
16229 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16230 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16231 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
16232 /* Side Pin: output 3 (0x0f) */
16233 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16234 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16235 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
16236
16237 /* Mic (rear) pin: input vref at 80% */
16238 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16239 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16240 /* Front Mic pin: input vref at 80% */
16241 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
16242 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16243 /* Line In pin: input */
16244 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16245 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16246 /* Line-2 In: Headphone output (output 0 - 0x0c) */
16247 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
16248 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16249 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
16250 /* CD pin widget for input */
16251 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16252
16253 { }
16254};
16255
Kailang Yangbdd148a2007-05-08 15:19:08 +020016256static struct hda_verb alc861vd_eapd_verbs[] = {
16257 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
16258 { }
16259};
16260
Kailang Yangf9423e72008-05-27 12:32:25 +020016261static struct hda_verb alc660vd_eapd_verbs[] = {
16262 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
16263 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
16264 { }
16265};
16266
Kailang Yangbdd148a2007-05-08 15:19:08 +020016267static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
16268 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16269 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16270 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
16271 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
Kailang Yangea1fb292008-08-26 12:58:38 +020016272 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
Kailang Yangbdd148a2007-05-08 15:19:08 +020016273 {}
16274};
16275
Kailang Yangbdd148a2007-05-08 15:19:08 +020016276static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
16277{
16278 unsigned int present;
16279 unsigned char bits;
16280
Wu Fengguang864f92b2009-11-18 12:38:02 +080016281 present = snd_hda_jack_detect(codec, 0x18);
Takashi Iwai47fd8302007-08-10 17:11:07 +020016282 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080016283
Takashi Iwai47fd8302007-08-10 17:11:07 +020016284 snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
16285 HDA_AMP_MUTE, bits);
Kailang Yangbdd148a2007-05-08 15:19:08 +020016286}
16287
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016288static void alc861vd_lenovo_setup(struct hda_codec *codec)
Kailang Yangbdd148a2007-05-08 15:19:08 +020016289{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016290 struct alc_spec *spec = codec->spec;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016291 spec->autocfg.hp_pins[0] = 0x1b;
16292 spec->autocfg.speaker_pins[0] = 0x14;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016293}
16294
16295static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
16296{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016297 alc_automute_amp(codec);
Kailang Yangbdd148a2007-05-08 15:19:08 +020016298 alc861vd_lenovo_mic_automute(codec);
16299}
16300
16301static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
16302 unsigned int res)
16303{
16304 switch (res >> 26) {
Kailang Yangbdd148a2007-05-08 15:19:08 +020016305 case ALC880_MIC_EVENT:
16306 alc861vd_lenovo_mic_automute(codec);
16307 break;
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016308 default:
16309 alc_automute_amp_unsol_event(codec, res);
16310 break;
Kailang Yangbdd148a2007-05-08 15:19:08 +020016311 }
16312}
16313
Kailang Yang272a5272007-05-14 11:00:38 +020016314static struct hda_verb alc861vd_dallas_verbs[] = {
16315 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16316 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16317 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16318 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
16319
16320 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16321 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
16322 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16323 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16324 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16325 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
16326 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
16327 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
Kailang Yangea1fb292008-08-26 12:58:38 +020016328
Kailang Yang272a5272007-05-14 11:00:38 +020016329 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16330 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16331 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16332 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16333 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16334 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16335 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
16336 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
16337
16338 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
16339 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16340 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
16341 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
16342 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16343 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16344 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16345 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
16346
16347 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
16348 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
16349 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
16350 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
16351
16352 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
Kailang Yangea1fb292008-08-26 12:58:38 +020016353 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yang272a5272007-05-14 11:00:38 +020016354 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
16355
16356 { } /* end */
16357};
16358
16359/* toggle speaker-output according to the hp-jack state */
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016360static void alc861vd_dallas_setup(struct hda_codec *codec)
Kailang Yang272a5272007-05-14 11:00:38 +020016361{
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016362 struct alc_spec *spec = codec->spec;
Kailang Yang272a5272007-05-14 11:00:38 +020016363
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016364 spec->autocfg.hp_pins[0] = 0x15;
16365 spec->autocfg.speaker_pins[0] = 0x14;
Kailang Yang272a5272007-05-14 11:00:38 +020016366}
16367
Takashi Iwaicb53c622007-08-10 17:21:45 +020016368#ifdef CONFIG_SND_HDA_POWER_SAVE
16369#define alc861vd_loopbacks alc880_loopbacks
16370#endif
16371
Sasha Alexandrdef319f2009-06-16 16:00:15 -040016372/* pcm configuration: identical with ALC880 */
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016373#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
16374#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
16375#define alc861vd_pcm_digital_playback alc880_pcm_digital_playback
16376#define alc861vd_pcm_digital_capture alc880_pcm_digital_capture
16377
16378/*
16379 * configuration and preset
16380 */
16381static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
16382 [ALC660VD_3ST] = "3stack-660",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020016383 [ALC660VD_3ST_DIG] = "3stack-660-digout",
Takashi Iwai13c94742008-11-05 08:06:08 +010016384 [ALC660VD_ASUS_V1S] = "asus-v1s",
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016385 [ALC861VD_3ST] = "3stack",
16386 [ALC861VD_3ST_DIG] = "3stack-digout",
16387 [ALC861VD_6ST_DIG] = "6stack-digout",
Kailang Yangbdd148a2007-05-08 15:19:08 +020016388 [ALC861VD_LENOVO] = "lenovo",
Kailang Yang272a5272007-05-14 11:00:38 +020016389 [ALC861VD_DALLAS] = "dallas",
Takashi Iwai983f8ae2007-08-15 16:44:04 +020016390 [ALC861VD_HP] = "hp",
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016391 [ALC861VD_AUTO] = "auto",
16392};
16393
16394static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
Takashi Iwaiac3e3742007-12-17 17:14:18 +010016395 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
16396 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
Takashi Iwai07e038b2007-02-15 18:23:41 +010016397 SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016398 /*SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),*/ /* auto */
Takashi Iwai13c94742008-11-05 08:06:08 +010016399 SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
Mike Crash6963f842007-06-25 12:12:51 +020016400 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016401 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
Takashi Iwaiac3e3742007-12-17 17:14:18 +010016402 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
Takashi Iwai38baf5a2007-08-16 17:52:43 +020016403 /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
Takashi Iwaice577e82009-08-03 08:23:52 +020016404 SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
Takashi Iwai542d7c62007-08-16 18:57:30 +020016405 SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
Tobin Davisb419f342008-03-07 11:57:51 +010016406 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
Takashi Iwai39c5d412007-08-15 16:24:17 +020016407 SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +010016408 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
Tobin Davis625dc0b2007-07-30 21:42:10 +020016409 SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016410 {}
16411};
16412
16413static struct alc_config_preset alc861vd_presets[] = {
16414 [ALC660VD_3ST] = {
16415 .mixers = { alc861vd_3st_mixer },
16416 .init_verbs = { alc861vd_volume_init_verbs,
16417 alc861vd_3stack_init_verbs },
16418 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
16419 .dac_nids = alc660vd_dac_nids,
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016420 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16421 .channel_mode = alc861vd_3stack_2ch_modes,
16422 .input_mux = &alc861vd_capture_source,
16423 },
Mike Crash6963f842007-06-25 12:12:51 +020016424 [ALC660VD_3ST_DIG] = {
16425 .mixers = { alc861vd_3st_mixer },
16426 .init_verbs = { alc861vd_volume_init_verbs,
16427 alc861vd_3stack_init_verbs },
16428 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
16429 .dac_nids = alc660vd_dac_nids,
16430 .dig_out_nid = ALC861VD_DIGOUT_NID,
Mike Crash6963f842007-06-25 12:12:51 +020016431 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16432 .channel_mode = alc861vd_3stack_2ch_modes,
16433 .input_mux = &alc861vd_capture_source,
16434 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016435 [ALC861VD_3ST] = {
16436 .mixers = { alc861vd_3st_mixer },
16437 .init_verbs = { alc861vd_volume_init_verbs,
16438 alc861vd_3stack_init_verbs },
16439 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16440 .dac_nids = alc861vd_dac_nids,
16441 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16442 .channel_mode = alc861vd_3stack_2ch_modes,
16443 .input_mux = &alc861vd_capture_source,
16444 },
16445 [ALC861VD_3ST_DIG] = {
16446 .mixers = { alc861vd_3st_mixer },
16447 .init_verbs = { alc861vd_volume_init_verbs,
16448 alc861vd_3stack_init_verbs },
16449 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16450 .dac_nids = alc861vd_dac_nids,
16451 .dig_out_nid = ALC861VD_DIGOUT_NID,
16452 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16453 .channel_mode = alc861vd_3stack_2ch_modes,
16454 .input_mux = &alc861vd_capture_source,
16455 },
16456 [ALC861VD_6ST_DIG] = {
16457 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
16458 .init_verbs = { alc861vd_volume_init_verbs,
16459 alc861vd_6stack_init_verbs },
16460 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16461 .dac_nids = alc861vd_dac_nids,
16462 .dig_out_nid = ALC861VD_DIGOUT_NID,
16463 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
16464 .channel_mode = alc861vd_6stack_modes,
16465 .input_mux = &alc861vd_capture_source,
16466 },
Kailang Yangbdd148a2007-05-08 15:19:08 +020016467 [ALC861VD_LENOVO] = {
16468 .mixers = { alc861vd_lenovo_mixer },
16469 .init_verbs = { alc861vd_volume_init_verbs,
16470 alc861vd_3stack_init_verbs,
16471 alc861vd_eapd_verbs,
16472 alc861vd_lenovo_unsol_verbs },
16473 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
16474 .dac_nids = alc660vd_dac_nids,
Kailang Yangbdd148a2007-05-08 15:19:08 +020016475 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16476 .channel_mode = alc861vd_3stack_2ch_modes,
16477 .input_mux = &alc861vd_capture_source,
16478 .unsol_event = alc861vd_lenovo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016479 .setup = alc861vd_lenovo_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016480 .init_hook = alc861vd_lenovo_init_hook,
Kailang Yangbdd148a2007-05-08 15:19:08 +020016481 },
Kailang Yang272a5272007-05-14 11:00:38 +020016482 [ALC861VD_DALLAS] = {
16483 .mixers = { alc861vd_dallas_mixer },
16484 .init_verbs = { alc861vd_dallas_verbs },
16485 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16486 .dac_nids = alc861vd_dac_nids,
Kailang Yang272a5272007-05-14 11:00:38 +020016487 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16488 .channel_mode = alc861vd_3stack_2ch_modes,
16489 .input_mux = &alc861vd_dallas_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016490 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016491 .setup = alc861vd_dallas_setup,
16492 .init_hook = alc_automute_amp,
Kailang Yangd1a991a2007-08-15 16:21:59 +020016493 },
16494 [ALC861VD_HP] = {
16495 .mixers = { alc861vd_hp_mixer },
16496 .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
16497 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
16498 .dac_nids = alc861vd_dac_nids,
Kailang Yangd1a991a2007-08-15 16:21:59 +020016499 .dig_out_nid = ALC861VD_DIGOUT_NID,
Kailang Yangd1a991a2007-08-15 16:21:59 +020016500 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16501 .channel_mode = alc861vd_3stack_2ch_modes,
16502 .input_mux = &alc861vd_hp_capture_source,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016503 .unsol_event = alc_automute_amp_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016504 .setup = alc861vd_dallas_setup,
16505 .init_hook = alc_automute_amp,
Kailang Yangea1fb292008-08-26 12:58:38 +020016506 },
Takashi Iwai13c94742008-11-05 08:06:08 +010016507 [ALC660VD_ASUS_V1S] = {
16508 .mixers = { alc861vd_lenovo_mixer },
16509 .init_verbs = { alc861vd_volume_init_verbs,
16510 alc861vd_3stack_init_verbs,
16511 alc861vd_eapd_verbs,
16512 alc861vd_lenovo_unsol_verbs },
16513 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
16514 .dac_nids = alc660vd_dac_nids,
16515 .dig_out_nid = ALC861VD_DIGOUT_NID,
16516 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
16517 .channel_mode = alc861vd_3stack_2ch_modes,
16518 .input_mux = &alc861vd_capture_source,
16519 .unsol_event = alc861vd_lenovo_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016520 .setup = alc861vd_lenovo_setup,
Takashi Iwaia9fd4f32009-05-08 15:57:59 +020016521 .init_hook = alc861vd_lenovo_init_hook,
Takashi Iwai13c94742008-11-05 08:06:08 +010016522 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016523};
16524
16525/*
16526 * BIOS auto configuration
16527 */
Takashi Iwai05f5f472009-08-25 13:10:18 +020016528static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
16529 const struct auto_pin_cfg *cfg)
16530{
Kailang Yang6227cdc2010-02-25 08:36:52 +010016531 return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
Takashi Iwai05f5f472009-08-25 13:10:18 +020016532}
16533
16534
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016535static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
16536 hda_nid_t nid, int pin_type, int dac_idx)
16537{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016538 alc_set_pin_output(codec, nid, pin_type);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016539}
16540
16541static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
16542{
16543 struct alc_spec *spec = codec->spec;
16544 int i;
16545
16546 for (i = 0; i <= HDA_SIDE; i++) {
16547 hda_nid_t nid = spec->autocfg.line_out_pins[i];
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020016548 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016549 if (nid)
16550 alc861vd_auto_set_output_and_unmute(codec, nid,
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020016551 pin_type, i);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016552 }
16553}
16554
16555
16556static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
16557{
16558 struct alc_spec *spec = codec->spec;
16559 hda_nid_t pin;
16560
16561 pin = spec->autocfg.hp_pins[0];
Sasha Alexandrdef319f2009-06-16 16:00:15 -040016562 if (pin) /* connect to front and use dac 0 */
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016563 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016564 pin = spec->autocfg.speaker_pins[0];
16565 if (pin)
16566 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016567}
16568
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016569#define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID
16570
16571static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
16572{
16573 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +020016574 struct auto_pin_cfg *cfg = &spec->autocfg;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016575 int i;
16576
Takashi Iwai66ceeb62010-08-30 13:05:52 +020016577 for (i = 0; i < cfg->num_inputs; i++) {
16578 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +020016579 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +010016580 alc_set_input_pin(codec, nid, i);
Takashi Iwaie82c0252009-03-23 15:17:38 +010016581 if (nid != ALC861VD_PIN_CD_NID &&
16582 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016583 snd_hda_codec_write(codec, nid, 0,
16584 AC_VERB_SET_AMP_GAIN_MUTE,
16585 AMP_OUT_MUTE);
16586 }
16587 }
16588}
16589
Takashi Iwaif511b012008-08-15 16:46:42 +020016590#define alc861vd_auto_init_input_src alc882_auto_init_input_src
16591
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016592#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)
16593#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)
16594
16595/* add playback controls from the parsed DAC table */
16596/* Based on ALC880 version. But ALC861VD has separate,
16597 * different NIDs for mute/unmute switch and volume control */
16598static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
16599 const struct auto_pin_cfg *cfg)
16600{
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016601 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
16602 hda_nid_t nid_v, nid_s;
16603 int i, err;
16604
16605 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016606 if (!spec->multiout.dac_nids[i])
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016607 continue;
16608 nid_v = alc861vd_idx_to_mixer_vol(
16609 alc880_dac_to_idx(
16610 spec->multiout.dac_nids[i]));
16611 nid_s = alc861vd_idx_to_mixer_switch(
16612 alc880_dac_to_idx(
16613 spec->multiout.dac_nids[i]));
16614
16615 if (i == 2) {
16616 /* Center/LFE */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016617 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
16618 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016619 HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
16620 HDA_OUTPUT));
16621 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016622 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016623 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
16624 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016625 HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
16626 HDA_OUTPUT));
16627 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016628 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016629 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
16630 "Center",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016631 HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
16632 HDA_INPUT));
16633 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016634 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016635 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
16636 "LFE",
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016637 HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
16638 HDA_INPUT));
16639 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016640 return err;
16641 } else {
Takashi Iwaia4fcd492009-08-25 16:12:15 +020016642 const char *pfx;
16643 if (cfg->line_outs == 1 &&
16644 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
16645 if (!cfg->hp_pins)
16646 pfx = "Speaker";
16647 else
16648 pfx = "PCM";
16649 } else
16650 pfx = chname[i];
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016651 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016652 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
16653 HDA_OUTPUT));
16654 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016655 return err;
Takashi Iwaia4fcd492009-08-25 16:12:15 +020016656 if (cfg->line_outs == 1 &&
16657 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
16658 pfx = "Speaker";
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016659 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Kailang Yangbdd148a2007-05-08 15:19:08 +020016660 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016661 HDA_INPUT));
16662 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016663 return err;
16664 }
16665 }
16666 return 0;
16667}
16668
16669/* add playback controls for speaker and HP outputs */
16670/* Based on ALC880 version. But ALC861VD has separate,
16671 * different NIDs for mute/unmute switch and volume control */
16672static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
16673 hda_nid_t pin, const char *pfx)
16674{
16675 hda_nid_t nid_v, nid_s;
16676 int err;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016677
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016678 if (!pin)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016679 return 0;
16680
16681 if (alc880_is_fixed_pin(pin)) {
16682 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
16683 /* specify the DAC as the extra output */
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016684 if (!spec->multiout.hp_nid)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016685 spec->multiout.hp_nid = nid_v;
16686 else
16687 spec->multiout.extra_out_nid[0] = nid_v;
16688 /* control HP volume/switch on the output mixer amp */
16689 nid_v = alc861vd_idx_to_mixer_vol(
16690 alc880_fixed_pin_idx(pin));
16691 nid_s = alc861vd_idx_to_mixer_switch(
16692 alc880_fixed_pin_idx(pin));
16693
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016694 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016695 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
16696 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016697 return err;
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016698 err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016699 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
16700 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016701 return err;
16702 } else if (alc880_is_multi_pin(pin)) {
16703 /* set manual connection */
16704 /* we have only a switch on HP-out PIN */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020016705 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016706 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
16707 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016708 return err;
16709 }
16710 return 0;
16711}
16712
16713/* parse the BIOS configuration and set up the alc_spec
16714 * return 1 if successful, 0 if the proper config is not found,
16715 * or a negative error code
16716 * Based on ALC880 version - had to change it to override
16717 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
16718static int alc861vd_parse_auto_config(struct hda_codec *codec)
16719{
16720 struct alc_spec *spec = codec->spec;
16721 int err;
16722 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
16723
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016724 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
16725 alc861vd_ignore);
16726 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016727 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016728 if (!spec->autocfg.line_outs)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016729 return 0; /* can't find valid BIOS pin config */
16730
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016731 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
16732 if (err < 0)
16733 return err;
16734 err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
16735 if (err < 0)
16736 return err;
16737 err = alc861vd_auto_create_extra_out(spec,
16738 spec->autocfg.speaker_pins[0],
16739 "Speaker");
16740 if (err < 0)
16741 return err;
16742 err = alc861vd_auto_create_extra_out(spec,
16743 spec->autocfg.hp_pins[0],
16744 "Headphone");
16745 if (err < 0)
16746 return err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020016747 err = alc861vd_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016748 if (err < 0)
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016749 return err;
16750
16751 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
16752
Takashi Iwai757899a2010-07-30 10:48:14 +020016753 alc_auto_parse_digital(codec);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016754
Takashi Iwai603c4012008-07-30 15:01:44 +020016755 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010016756 add_mixer(spec, spec->kctls.list);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016757
Takashi Iwaid88897e2008-10-31 15:01:37 +010016758 add_verb(spec, alc861vd_volume_init_verbs);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016759
16760 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020016761 spec->input_mux = &spec->private_imux[0];
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016762
Takashi Iwai776e1842007-08-29 15:07:11 +020016763 err = alc_auto_add_mic_boost(codec);
16764 if (err < 0)
16765 return err;
16766
Kailang Yang6227cdc2010-02-25 08:36:52 +010016767 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020016768
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016769 return 1;
16770}
16771
16772/* additional initialization for auto-configuration model */
16773static void alc861vd_auto_init(struct hda_codec *codec)
16774{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016775 struct alc_spec *spec = codec->spec;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016776 alc861vd_auto_init_multi_out(codec);
16777 alc861vd_auto_init_hp_out(codec);
16778 alc861vd_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020016779 alc861vd_auto_init_input_src(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +020016780 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010016781 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020016782 alc_inithook(codec);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016783}
16784
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016785enum {
16786 ALC660VD_FIX_ASUS_GPIO1
16787};
16788
16789/* reset GPIO1 */
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016790static const struct alc_fixup alc861vd_fixups[] = {
16791 [ALC660VD_FIX_ASUS_GPIO1] = {
Takashi Iwai73413b12010-08-30 09:39:57 +020016792 .verbs = (const struct hda_verb[]) {
16793 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
16794 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
16795 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
16796 { }
16797 }
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016798 },
16799};
16800
16801static struct snd_pci_quirk alc861vd_fixup_tbl[] = {
16802 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
16803 {}
16804};
16805
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016806static int patch_alc861vd(struct hda_codec *codec)
16807{
16808 struct alc_spec *spec;
16809 int err, board_config;
16810
16811 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
16812 if (spec == NULL)
16813 return -ENOMEM;
16814
16815 codec->spec = spec;
16816
16817 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
16818 alc861vd_models,
16819 alc861vd_cfg_tbl);
16820
16821 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020016822 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
16823 codec->chip_name);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016824 board_config = ALC861VD_AUTO;
16825 }
16826
Takashi Iwai7fa90e82010-04-12 08:49:00 +020016827 if (board_config == ALC861VD_AUTO)
16828 alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 1);
Takashi Iwaif8f25ba2009-10-06 08:31:29 +020016829
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016830 if (board_config == ALC861VD_AUTO) {
16831 /* automatic parse from the BIOS config */
16832 err = alc861vd_parse_auto_config(codec);
16833 if (err < 0) {
16834 alc_free(codec);
16835 return err;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020016836 } else if (!err) {
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016837 printk(KERN_INFO
16838 "hda_codec: Cannot set up configuration "
16839 "from BIOS. Using base mode...\n");
16840 board_config = ALC861VD_3ST;
16841 }
16842 }
16843
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090016844 err = snd_hda_attach_beep_device(codec, 0x23);
16845 if (err < 0) {
16846 alc_free(codec);
16847 return err;
16848 }
16849
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016850 if (board_config != ALC861VD_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020016851 setup_preset(codec, &alc861vd_presets[board_config]);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016852
Kailang Yang2f893282008-05-27 12:14:47 +020016853 if (codec->vendor_id == 0x10ec0660) {
Kailang Yangf9423e72008-05-27 12:32:25 +020016854 /* always turn on EAPD */
Takashi Iwaid88897e2008-10-31 15:01:37 +010016855 add_verb(spec, alc660vd_eapd_verbs);
Kailang Yang2f893282008-05-27 12:14:47 +020016856 }
16857
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016858 spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
16859 spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
16860
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016861 spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
16862 spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
16863
Takashi Iwaidd704692009-08-11 08:45:11 +020016864 if (!spec->adc_nids) {
16865 spec->adc_nids = alc861vd_adc_nids;
16866 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
16867 }
16868 if (!spec->capsrc_nids)
16869 spec->capsrc_nids = alc861vd_capsrc_nids;
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016870
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016871 set_capture_mixer(codec);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010016872 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016873
Takashi Iwai2134ea42008-01-10 16:53:55 +010016874 spec->vmaster_nid = 0x02;
16875
Takashi Iwai7fa90e82010-04-12 08:49:00 +020016876 if (board_config == ALC861VD_AUTO)
16877 alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 0);
16878
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016879 codec->patch_ops = alc_patch_ops;
16880
16881 if (board_config == ALC861VD_AUTO)
16882 spec->init_hook = alc861vd_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020016883#ifdef CONFIG_SND_HDA_POWER_SAVE
16884 if (!spec->loopback.amplist)
16885 spec->loopback.amplist = alc861vd_loopbacks;
16886#endif
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010016887
16888 return 0;
16889}
16890
16891/*
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016892 * ALC662 support
16893 *
16894 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
16895 * configuration. Each pin widget can choose any input DACs and a mixer.
16896 * Each ADC is connected from a mixer of all inputs. This makes possible
16897 * 6-channel independent captures.
16898 *
16899 * In addition, an independent DAC for the multi-playback (not used in this
16900 * driver yet).
16901 */
16902#define ALC662_DIGOUT_NID 0x06
16903#define ALC662_DIGIN_NID 0x0a
16904
16905static hda_nid_t alc662_dac_nids[4] = {
16906 /* front, rear, clfe, rear_surr */
16907 0x02, 0x03, 0x04
16908};
16909
Kailang Yang622e84c2009-04-21 07:39:04 +020016910static hda_nid_t alc272_dac_nids[2] = {
16911 0x02, 0x03
16912};
16913
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016914static hda_nid_t alc662_adc_nids[2] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016915 /* ADC1-2 */
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016916 0x09, 0x08
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016917};
Takashi Iwaie1406342008-02-11 18:32:32 +010016918
Kailang Yang622e84c2009-04-21 07:39:04 +020016919static hda_nid_t alc272_adc_nids[1] = {
16920 /* ADC1-2 */
16921 0x08,
16922};
16923
Takashi Iwaib59bdf32009-08-11 09:47:30 +020016924static hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
Kailang Yang622e84c2009-04-21 07:39:04 +020016925static hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
16926
Takashi Iwaie1406342008-02-11 18:32:32 +010016927
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016928/* input MUX */
16929/* FIXME: should be a matrix-type input source selection */
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016930static struct hda_input_mux alc662_capture_source = {
16931 .num_items = 4,
16932 .items = {
16933 { "Mic", 0x0 },
16934 { "Front Mic", 0x1 },
16935 { "Line", 0x2 },
16936 { "CD", 0x4 },
16937 },
16938};
16939
16940static struct hda_input_mux alc662_lenovo_101e_capture_source = {
16941 .num_items = 2,
16942 .items = {
16943 { "Mic", 0x1 },
16944 { "Line", 0x2 },
16945 },
16946};
Kailang Yang291702f2007-10-16 14:28:03 +020016947
Kailang Yang6dda9f42008-05-27 12:05:31 +020016948static struct hda_input_mux alc663_capture_source = {
16949 .num_items = 3,
16950 .items = {
16951 { "Mic", 0x0 },
16952 { "Front Mic", 0x1 },
16953 { "Line", 0x2 },
16954 },
16955};
16956
Takashi Iwai4f5d17062009-08-11 18:17:46 +020016957#if 0 /* set to 1 for testing other input sources below */
Chris Pockelé9541ba12009-05-12 08:08:53 +020016958static struct hda_input_mux alc272_nc10_capture_source = {
16959 .num_items = 16,
16960 .items = {
16961 { "Autoselect Mic", 0x0 },
16962 { "Internal Mic", 0x1 },
16963 { "In-0x02", 0x2 },
16964 { "In-0x03", 0x3 },
16965 { "In-0x04", 0x4 },
16966 { "In-0x05", 0x5 },
16967 { "In-0x06", 0x6 },
16968 { "In-0x07", 0x7 },
16969 { "In-0x08", 0x8 },
16970 { "In-0x09", 0x9 },
16971 { "In-0x0a", 0x0a },
16972 { "In-0x0b", 0x0b },
16973 { "In-0x0c", 0x0c },
16974 { "In-0x0d", 0x0d },
16975 { "In-0x0e", 0x0e },
16976 { "In-0x0f", 0x0f },
16977 },
16978};
16979#endif
16980
Kailang Yangbc9f98a2007-04-12 13:06:07 +020016981/*
16982 * 2ch mode
16983 */
16984static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
16985 { 2, NULL }
16986};
16987
16988/*
16989 * 2ch mode
16990 */
16991static struct hda_verb alc662_3ST_ch2_init[] = {
16992 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
16993 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
16994 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
16995 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
16996 { } /* end */
16997};
16998
16999/*
17000 * 6ch mode
17001 */
17002static struct hda_verb alc662_3ST_ch6_init[] = {
17003 { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17004 { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
17005 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
17006 { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17007 { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
17008 { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
17009 { } /* end */
17010};
17011
17012static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
17013 { 2, alc662_3ST_ch2_init },
17014 { 6, alc662_3ST_ch6_init },
17015};
17016
17017/*
17018 * 2ch mode
17019 */
17020static struct hda_verb alc662_sixstack_ch6_init[] = {
17021 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
17022 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
17023 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17024 { } /* end */
17025};
17026
17027/*
17028 * 6ch mode
17029 */
17030static struct hda_verb alc662_sixstack_ch8_init[] = {
17031 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17032 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17033 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
17034 { } /* end */
17035};
17036
17037static struct hda_channel_mode alc662_5stack_modes[2] = {
17038 { 2, alc662_sixstack_ch6_init },
17039 { 6, alc662_sixstack_ch8_init },
17040};
17041
17042/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
17043 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
17044 */
17045
17046static struct snd_kcontrol_new alc662_base_mixer[] = {
17047 /* output mixer control */
17048 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010017049 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017050 HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010017051 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017052 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17053 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010017054 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
17055 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017056 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17057
17058 /*Input mixer control */
17059 HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
17060 HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
17061 HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
17062 HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
17063 HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
17064 HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
17065 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
17066 HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017067 { } /* end */
17068};
17069
17070static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
17071 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010017072 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017073 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17074 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
17075 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
17076 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17077 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17078 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17079 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17080 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17081 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017082 { } /* end */
17083};
17084
17085static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
17086 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010017087 HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017088 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010017089 HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017090 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17091 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Herton Ronaldo Krzesinski7055ad82008-03-14 12:52:20 +010017092 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
17093 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017094 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17095 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
17096 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
17097 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17098 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17099 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17100 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17101 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17102 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017103 { } /* end */
17104};
17105
17106static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
17107 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17108 HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
Takashi Iwai86cd9292008-01-28 18:09:56 +010017109 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17110 HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017111 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17112 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17113 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17114 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17115 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017116 { } /* end */
17117};
17118
Kailang Yang291702f2007-10-16 14:28:03 +020017119static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020017120 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17121 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yang291702f2007-10-16 14:28:03 +020017122
17123 HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT),
17124 HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17125 HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17126
17127 HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),
17128 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17129 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17130 { } /* end */
17131};
17132
Kailang Yang8c427222008-01-10 13:03:59 +010017133static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
Takashi Iwai42171c12009-05-08 14:11:43 +020017134 ALC262_HIPPO_MASTER_SWITCH,
17135 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010017136 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010017137 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
17138 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
Kailang Yang8c427222008-01-10 13:03:59 +010017139 HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
17140 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17141 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17142 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17143 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17144 { } /* end */
17145};
17146
Kailang Yangf1d4e282008-08-26 14:03:29 +020017147static struct hda_bind_ctls alc663_asus_bind_master_vol = {
17148 .ops = &snd_hda_bind_vol,
17149 .values = {
17150 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
17151 HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
17152 0
17153 },
17154};
17155
17156static struct hda_bind_ctls alc663_asus_one_bind_switch = {
17157 .ops = &snd_hda_bind_sw,
17158 .values = {
17159 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17160 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17161 0
17162 },
17163};
17164
Kailang Yang6dda9f42008-05-27 12:05:31 +020017165static struct snd_kcontrol_new alc663_m51va_mixer[] = {
Kailang Yangf1d4e282008-08-26 14:03:29 +020017166 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17167 HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
17168 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17169 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17170 { } /* end */
17171};
17172
17173static struct hda_bind_ctls alc663_asus_tree_bind_switch = {
17174 .ops = &snd_hda_bind_sw,
17175 .values = {
17176 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17177 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17178 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17179 0
17180 },
17181};
17182
17183static struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
17184 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17185 HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
17186 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17187 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17188 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17189 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17190
17191 { } /* end */
17192};
17193
17194static struct hda_bind_ctls alc663_asus_four_bind_switch = {
17195 .ops = &snd_hda_bind_sw,
17196 .values = {
17197 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17198 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17199 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
17200 0
17201 },
17202};
17203
17204static struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
17205 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17206 HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
17207 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17208 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17209 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17210 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17211 { } /* end */
17212};
17213
17214static struct snd_kcontrol_new alc662_1bjd_mixer[] = {
Kailang Yang6dda9f42008-05-27 12:05:31 +020017215 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17216 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
Kailang Yangf1d4e282008-08-26 14:03:29 +020017217 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17218 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17219 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17220 HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17221 HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17222 { } /* end */
17223};
17224
17225static struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
17226 .ops = &snd_hda_bind_vol,
17227 .values = {
17228 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
17229 HDA_COMPOSE_AMP_VAL(0x04, 3, 0, HDA_OUTPUT),
17230 0
17231 },
17232};
17233
17234static struct hda_bind_ctls alc663_asus_two_bind_switch = {
17235 .ops = &snd_hda_bind_sw,
17236 .values = {
17237 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17238 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT),
17239 0
17240 },
17241};
17242
17243static struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
17244 HDA_BIND_VOL("Master Playback Volume",
17245 &alc663_asus_two_bind_master_vol),
17246 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
17247 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
Kailang Yang6dda9f42008-05-27 12:05:31 +020017248 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17249 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17250 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yangf1d4e282008-08-26 14:03:29 +020017251 { } /* end */
17252};
17253
17254static struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
17255 HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
17256 HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
17257 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17258 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17259 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17260 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
Kailang Yang6dda9f42008-05-27 12:05:31 +020017261 { } /* end */
17262};
17263
17264static struct snd_kcontrol_new alc663_g71v_mixer[] = {
17265 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17266 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17267 HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
17268 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17269 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17270
17271 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17272 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17273 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17274 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17275 { } /* end */
17276};
17277
17278static struct snd_kcontrol_new alc663_g50v_mixer[] = {
17279 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
17280 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
17281 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17282
17283 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17284 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17285 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17286 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17287 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
17288 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
17289 { } /* end */
17290};
17291
Kailang Yangebb83ee2009-12-17 12:23:00 +010017292static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
17293 .ops = &snd_hda_bind_sw,
17294 .values = {
17295 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17296 HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
17297 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
17298 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
17299 HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
17300 0
17301 },
17302};
17303
17304static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
17305 .ops = &snd_hda_bind_sw,
17306 .values = {
17307 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
17308 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
17309 0
17310 },
17311};
17312
17313static struct snd_kcontrol_new alc663_mode7_mixer[] = {
17314 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
17315 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
17316 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
17317 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
17318 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17319 HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17320 HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17321 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
17322 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
17323 { } /* end */
17324};
17325
17326static struct snd_kcontrol_new alc663_mode8_mixer[] = {
17327 HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
17328 HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
17329 HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
17330 HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
17331 HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
17332 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
17333 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
17334 { } /* end */
17335};
17336
17337
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017338static struct snd_kcontrol_new alc662_chmode_mixer[] = {
17339 {
17340 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
17341 .name = "Channel Mode",
17342 .info = alc_ch_mode_info,
17343 .get = alc_ch_mode_get,
17344 .put = alc_ch_mode_put,
17345 },
17346 { } /* end */
17347};
17348
17349static struct hda_verb alc662_init_verbs[] = {
17350 /* ADC: mute amp left and right */
17351 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17352 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017353
Kailang Yangb60dd392007-09-20 12:50:29 +020017354 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17355 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17356 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17357 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17358 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17359 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017360
17361 /* Front Pin: output 0 (0x0c) */
17362 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17363 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17364
17365 /* Rear Pin: output 1 (0x0d) */
17366 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17367 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17368
17369 /* CLFE Pin: output 2 (0x0e) */
17370 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17371 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17372
17373 /* Mic (rear) pin: input vref at 80% */
17374 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
17375 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
17376 /* Front Mic pin: input vref at 80% */
17377 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
17378 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
17379 /* Line In pin: input */
17380 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17381 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
17382 /* Line-2 In: Headphone output (output 0 - 0x0c) */
17383 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17384 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17385 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
17386 /* CD pin widget for input */
17387 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17388
17389 /* FIXME: use matrix-type input source selection */
17390 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
17391 /* Input mixer */
17392 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yang291702f2007-10-16 14:28:03 +020017393 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
Kailang Yang6dda9f42008-05-27 12:05:31 +020017394
17395 /* always trun on EAPD */
17396 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
17397 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
17398
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017399 { }
17400};
17401
Kailang Yangcec27c82010-02-04 14:18:18 +010017402static struct hda_verb alc663_init_verbs[] = {
17403 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17404 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17405 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17406 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17407 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17408 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17409 { }
17410};
17411
17412static struct hda_verb alc272_init_verbs[] = {
17413 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17414 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
17415 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17416 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17417 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17418 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17419 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
17420 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17421 { }
17422};
17423
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017424static struct hda_verb alc662_sue_init_verbs[] = {
17425 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
17426 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
Kailang Yang291702f2007-10-16 14:28:03 +020017427 {}
17428};
17429
17430static struct hda_verb alc662_eeepc_sue_init_verbs[] = {
17431 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17432 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17433 {}
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017434};
17435
Kailang Yang8c427222008-01-10 13:03:59 +010017436/* Set Unsolicited Event*/
17437static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
17438 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17439 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17440 {}
17441};
17442
Kailang Yang6dda9f42008-05-27 12:05:31 +020017443static struct hda_verb alc663_m51va_init_verbs[] = {
Kailang Yangf1d4e282008-08-26 14:03:29 +020017444 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17445 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yang6dda9f42008-05-27 12:05:31 +020017446 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17447 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangf1d4e282008-08-26 14:03:29 +020017448 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17449 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17450 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
Kailang Yang6dda9f42008-05-27 12:05:31 +020017451 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17452 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17453 {}
17454};
17455
Kailang Yangf1d4e282008-08-26 14:03:29 +020017456static struct hda_verb alc663_21jd_amic_init_verbs[] = {
17457 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17458 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17459 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17460 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17461 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17462 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17463 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17464 {}
17465};
17466
17467static struct hda_verb alc662_1bjd_amic_init_verbs[] = {
17468 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17469 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17470 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17471 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
17472 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17473 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17474 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17475 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17476 {}
17477};
17478
17479static struct hda_verb alc663_15jd_amic_init_verbs[] = {
17480 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17481 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17482 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17483 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17484 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17485 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17486 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17487 {}
17488};
17489
17490static struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
17491 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17492 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17493 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17494 {0x21, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
17495 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17496 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17497 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
17498 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17499 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17500 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17501 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17502 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17503 {}
17504};
17505
17506static struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
17507 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17508 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17509 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17510 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17511 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17512 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17513 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17514 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17515 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
17516 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17517 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17518 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17519 {}
17520};
17521
Kailang Yang6dda9f42008-05-27 12:05:31 +020017522static struct hda_verb alc663_g71v_init_verbs[] = {
17523 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17524 /* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
17525 /* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
17526
17527 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17528 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17529 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
17530
17531 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
17532 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
17533 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
17534 {}
17535};
17536
17537static struct hda_verb alc663_g50v_init_verbs[] = {
17538 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17539 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17540 {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
17541
17542 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17543 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17544 {}
17545};
17546
Kailang Yangf1d4e282008-08-26 14:03:29 +020017547static struct hda_verb alc662_ecs_init_verbs[] = {
17548 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
17549 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17550 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17551 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17552 {}
17553};
17554
Kailang Yang622e84c2009-04-21 07:39:04 +020017555static struct hda_verb alc272_dell_zm1_init_verbs[] = {
17556 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17557 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17558 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17559 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17560 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17561 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17562 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17563 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17564 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
17565 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17566 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17567 {}
17568};
17569
17570static struct hda_verb alc272_dell_init_verbs[] = {
17571 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17572 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17573 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17574 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17575 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17576 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17577 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17578 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17579 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
17580 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17581 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17582 {}
17583};
17584
Kailang Yangebb83ee2009-12-17 12:23:00 +010017585static struct hda_verb alc663_mode7_init_verbs[] = {
17586 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17587 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17588 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17589 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17590 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17591 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17592 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
17593 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17594 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17595 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17596 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17597 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
17598 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17599 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17600 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17601 {}
17602};
17603
17604static struct hda_verb alc663_mode8_init_verbs[] = {
17605 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17606 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17607 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17608 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
17609 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17610 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
17611 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17612 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
17613 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
17614 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
17615 {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
17616 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
17617 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
17618 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17619 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
17620 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
17621 {}
17622};
17623
Kailang Yangf1d4e282008-08-26 14:03:29 +020017624static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
17625 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
17626 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
17627 { } /* end */
17628};
17629
Kailang Yang622e84c2009-04-21 07:39:04 +020017630static struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
17631 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
17632 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
17633 { } /* end */
17634};
17635
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017636static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
17637{
17638 unsigned int present;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017639 unsigned char bits;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017640
Wu Fengguang864f92b2009-11-18 12:38:02 +080017641 present = snd_hda_jack_detect(codec, 0x14);
Takashi Iwai47fd8302007-08-10 17:11:07 +020017642 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080017643
Takashi Iwai47fd8302007-08-10 17:11:07 +020017644 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
17645 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017646}
17647
17648static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
17649{
17650 unsigned int present;
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020017651 unsigned char bits;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017652
Wu Fengguang864f92b2009-11-18 12:38:02 +080017653 present = snd_hda_jack_detect(codec, 0x1b);
Takashi Iwai47fd8302007-08-10 17:11:07 +020017654 bits = present ? HDA_AMP_MUTE : 0;
Wu Fengguang864f92b2009-11-18 12:38:02 +080017655
Takashi Iwai47fd8302007-08-10 17:11:07 +020017656 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
17657 HDA_AMP_MUTE, bits);
17658 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
17659 HDA_AMP_MUTE, bits);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020017660}
17661
17662static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
17663 unsigned int res)
17664{
17665 if ((res >> 26) == ALC880_HP_EVENT)
17666 alc662_lenovo_101e_all_automute(codec);
17667 if ((res >> 26) == ALC880_FRONT_EVENT)
17668 alc662_lenovo_101e_ispeaker_automute(codec);
17669}
17670
Kailang Yang291702f2007-10-16 14:28:03 +020017671/* unsolicited event for HP jack sensing */
17672static void alc662_eeepc_unsol_event(struct hda_codec *codec,
17673 unsigned int res)
17674{
Kailang Yang291702f2007-10-16 14:28:03 +020017675 if ((res >> 26) == ALC880_MIC_EVENT)
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017676 alc_mic_automute(codec);
Takashi Iwai42171c12009-05-08 14:11:43 +020017677 else
17678 alc262_hippo_unsol_event(codec, res);
Kailang Yang291702f2007-10-16 14:28:03 +020017679}
17680
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017681static void alc662_eeepc_setup(struct hda_codec *codec)
Kailang Yang291702f2007-10-16 14:28:03 +020017682{
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017683 struct alc_spec *spec = codec->spec;
17684
17685 alc262_hippo1_setup(codec);
17686 spec->ext_mic.pin = 0x18;
17687 spec->ext_mic.mux_idx = 0;
17688 spec->int_mic.pin = 0x19;
17689 spec->int_mic.mux_idx = 1;
17690 spec->auto_mic = 1;
Kailang Yang291702f2007-10-16 14:28:03 +020017691}
17692
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017693static void alc662_eeepc_inithook(struct hda_codec *codec)
17694{
17695 alc262_hippo_automute(codec);
17696 alc_mic_automute(codec);
17697}
17698
17699static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
Kailang Yang8c427222008-01-10 13:03:59 +010017700{
Takashi Iwai42171c12009-05-08 14:11:43 +020017701 struct alc_spec *spec = codec->spec;
17702
17703 spec->autocfg.hp_pins[0] = 0x14;
17704 spec->autocfg.speaker_pins[0] = 0x1b;
Kailang Yang8c427222008-01-10 13:03:59 +010017705}
17706
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017707#define alc662_eeepc_ep20_inithook alc262_hippo_master_update
17708
Kailang Yang6dda9f42008-05-27 12:05:31 +020017709static void alc663_m51va_speaker_automute(struct hda_codec *codec)
17710{
17711 unsigned int present;
17712 unsigned char bits;
17713
Wu Fengguang864f92b2009-11-18 12:38:02 +080017714 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017715 bits = present ? HDA_AMP_MUTE : 0;
Kailang Yangf1d4e282008-08-26 14:03:29 +020017716 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017717 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017718 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017719 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017720}
17721
17722static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
17723{
17724 unsigned int present;
17725 unsigned char bits;
17726
Wu Fengguang864f92b2009-11-18 12:38:02 +080017727 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017728 bits = present ? HDA_AMP_MUTE : 0;
17729 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017730 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017731 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017732 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017733 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017734 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017735 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017736 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017737}
17738
17739static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
17740{
17741 unsigned int present;
17742 unsigned char bits;
17743
Wu Fengguang864f92b2009-11-18 12:38:02 +080017744 present = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017745 bits = present ? HDA_AMP_MUTE : 0;
17746 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017747 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017748 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017749 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017750 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017751 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017752 snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017753 HDA_AMP_MUTE, bits);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017754}
17755
17756static void alc662_f5z_speaker_automute(struct hda_codec *codec)
17757{
17758 unsigned int present;
17759 unsigned char bits;
17760
Wu Fengguang864f92b2009-11-18 12:38:02 +080017761 present = snd_hda_jack_detect(codec, 0x1b);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017762 bits = present ? 0 : PIN_OUT;
17763 snd_hda_codec_write(codec, 0x14, 0,
17764 AC_VERB_SET_PIN_WIDGET_CONTROL, bits);
17765}
17766
17767static void alc663_two_hp_m1_speaker_automute(struct hda_codec *codec)
17768{
17769 unsigned int present1, present2;
17770
Wu Fengguang864f92b2009-11-18 12:38:02 +080017771 present1 = snd_hda_jack_detect(codec, 0x21);
17772 present2 = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017773
17774 if (present1 || present2) {
17775 snd_hda_codec_write_cache(codec, 0x14, 0,
17776 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17777 } else {
17778 snd_hda_codec_write_cache(codec, 0x14, 0,
17779 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17780 }
17781}
17782
17783static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
17784{
17785 unsigned int present1, present2;
17786
Wu Fengguang864f92b2009-11-18 12:38:02 +080017787 present1 = snd_hda_jack_detect(codec, 0x1b);
17788 present2 = snd_hda_jack_detect(codec, 0x15);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017789
17790 if (present1 || present2) {
17791 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017792 HDA_AMP_MUTE, HDA_AMP_MUTE);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017793 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017794 HDA_AMP_MUTE, HDA_AMP_MUTE);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017795 } else {
17796 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017797 HDA_AMP_MUTE, 0);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017798 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
Takashi Iwai5dbd5ec2010-03-29 09:16:24 +020017799 HDA_AMP_MUTE, 0);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017800 }
Kailang Yang6dda9f42008-05-27 12:05:31 +020017801}
17802
Kailang Yangebb83ee2009-12-17 12:23:00 +010017803static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec)
17804{
17805 unsigned int present1, present2;
17806
17807 present1 = snd_hda_codec_read(codec, 0x1b, 0,
17808 AC_VERB_GET_PIN_SENSE, 0)
17809 & AC_PINSENSE_PRESENCE;
17810 present2 = snd_hda_codec_read(codec, 0x21, 0,
17811 AC_VERB_GET_PIN_SENSE, 0)
17812 & AC_PINSENSE_PRESENCE;
17813
17814 if (present1 || present2) {
17815 snd_hda_codec_write_cache(codec, 0x14, 0,
17816 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17817 snd_hda_codec_write_cache(codec, 0x17, 0,
17818 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17819 } else {
17820 snd_hda_codec_write_cache(codec, 0x14, 0,
17821 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17822 snd_hda_codec_write_cache(codec, 0x17, 0,
17823 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17824 }
17825}
17826
17827static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec)
17828{
17829 unsigned int present1, present2;
17830
17831 present1 = snd_hda_codec_read(codec, 0x21, 0,
17832 AC_VERB_GET_PIN_SENSE, 0)
17833 & AC_PINSENSE_PRESENCE;
17834 present2 = snd_hda_codec_read(codec, 0x15, 0,
17835 AC_VERB_GET_PIN_SENSE, 0)
17836 & AC_PINSENSE_PRESENCE;
17837
17838 if (present1 || present2) {
17839 snd_hda_codec_write_cache(codec, 0x14, 0,
17840 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17841 snd_hda_codec_write_cache(codec, 0x17, 0,
17842 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
17843 } else {
17844 snd_hda_codec_write_cache(codec, 0x14, 0,
17845 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17846 snd_hda_codec_write_cache(codec, 0x17, 0,
17847 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
17848 }
17849}
17850
Kailang Yang6dda9f42008-05-27 12:05:31 +020017851static void alc663_m51va_unsol_event(struct hda_codec *codec,
17852 unsigned int res)
17853{
17854 switch (res >> 26) {
17855 case ALC880_HP_EVENT:
17856 alc663_m51va_speaker_automute(codec);
17857 break;
17858 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017859 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017860 break;
17861 }
17862}
17863
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017864static void alc663_m51va_setup(struct hda_codec *codec)
17865{
17866 struct alc_spec *spec = codec->spec;
17867 spec->ext_mic.pin = 0x18;
17868 spec->ext_mic.mux_idx = 0;
17869 spec->int_mic.pin = 0x12;
Kailang Yangebb83ee2009-12-17 12:23:00 +010017870 spec->int_mic.mux_idx = 9;
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017871 spec->auto_mic = 1;
17872}
17873
Kailang Yang6dda9f42008-05-27 12:05:31 +020017874static void alc663_m51va_inithook(struct hda_codec *codec)
17875{
17876 alc663_m51va_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017877 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020017878}
17879
Kailang Yangf1d4e282008-08-26 14:03:29 +020017880/* ***************** Mode1 ******************************/
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017881#define alc663_mode1_unsol_event alc663_m51va_unsol_event
Kailang Yangebb83ee2009-12-17 12:23:00 +010017882
17883static void alc663_mode1_setup(struct hda_codec *codec)
17884{
17885 struct alc_spec *spec = codec->spec;
17886 spec->ext_mic.pin = 0x18;
17887 spec->ext_mic.mux_idx = 0;
17888 spec->int_mic.pin = 0x19;
17889 spec->int_mic.mux_idx = 1;
17890 spec->auto_mic = 1;
17891}
17892
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017893#define alc663_mode1_inithook alc663_m51va_inithook
Kailang Yangf1d4e282008-08-26 14:03:29 +020017894
Kailang Yangf1d4e282008-08-26 14:03:29 +020017895/* ***************** Mode2 ******************************/
17896static void alc662_mode2_unsol_event(struct hda_codec *codec,
17897 unsigned int res)
17898{
17899 switch (res >> 26) {
17900 case ALC880_HP_EVENT:
17901 alc662_f5z_speaker_automute(codec);
17902 break;
17903 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017904 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017905 break;
17906 }
17907}
17908
Kailang Yangebb83ee2009-12-17 12:23:00 +010017909#define alc662_mode2_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017910
Kailang Yangf1d4e282008-08-26 14:03:29 +020017911static void alc662_mode2_inithook(struct hda_codec *codec)
17912{
17913 alc662_f5z_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017914 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017915}
17916/* ***************** Mode3 ******************************/
17917static void alc663_mode3_unsol_event(struct hda_codec *codec,
17918 unsigned int res)
17919{
17920 switch (res >> 26) {
17921 case ALC880_HP_EVENT:
17922 alc663_two_hp_m1_speaker_automute(codec);
17923 break;
17924 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017925 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017926 break;
17927 }
17928}
17929
Kailang Yangebb83ee2009-12-17 12:23:00 +010017930#define alc663_mode3_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017931
Kailang Yangf1d4e282008-08-26 14:03:29 +020017932static void alc663_mode3_inithook(struct hda_codec *codec)
17933{
17934 alc663_two_hp_m1_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017935 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017936}
17937/* ***************** Mode4 ******************************/
17938static void alc663_mode4_unsol_event(struct hda_codec *codec,
17939 unsigned int res)
17940{
17941 switch (res >> 26) {
17942 case ALC880_HP_EVENT:
17943 alc663_21jd_two_speaker_automute(codec);
17944 break;
17945 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017946 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017947 break;
17948 }
17949}
17950
Kailang Yangebb83ee2009-12-17 12:23:00 +010017951#define alc663_mode4_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017952
Kailang Yangf1d4e282008-08-26 14:03:29 +020017953static void alc663_mode4_inithook(struct hda_codec *codec)
17954{
17955 alc663_21jd_two_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017956 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017957}
17958/* ***************** Mode5 ******************************/
17959static void alc663_mode5_unsol_event(struct hda_codec *codec,
17960 unsigned int res)
17961{
17962 switch (res >> 26) {
17963 case ALC880_HP_EVENT:
17964 alc663_15jd_two_speaker_automute(codec);
17965 break;
17966 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017967 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017968 break;
17969 }
17970}
17971
Kailang Yangebb83ee2009-12-17 12:23:00 +010017972#define alc663_mode5_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017973
Kailang Yangf1d4e282008-08-26 14:03:29 +020017974static void alc663_mode5_inithook(struct hda_codec *codec)
17975{
17976 alc663_15jd_two_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017977 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017978}
17979/* ***************** Mode6 ******************************/
17980static void alc663_mode6_unsol_event(struct hda_codec *codec,
17981 unsigned int res)
17982{
17983 switch (res >> 26) {
17984 case ALC880_HP_EVENT:
17985 alc663_two_hp_m2_speaker_automute(codec);
17986 break;
17987 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017988 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017989 break;
17990 }
17991}
17992
Kailang Yangebb83ee2009-12-17 12:23:00 +010017993#define alc663_mode6_setup alc663_mode1_setup
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017994
Kailang Yangf1d4e282008-08-26 14:03:29 +020017995static void alc663_mode6_inithook(struct hda_codec *codec)
17996{
17997 alc663_two_hp_m2_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020017998 alc_mic_automute(codec);
Kailang Yangf1d4e282008-08-26 14:03:29 +020017999}
18000
Kailang Yangebb83ee2009-12-17 12:23:00 +010018001/* ***************** Mode7 ******************************/
18002static void alc663_mode7_unsol_event(struct hda_codec *codec,
18003 unsigned int res)
18004{
18005 switch (res >> 26) {
18006 case ALC880_HP_EVENT:
18007 alc663_two_hp_m7_speaker_automute(codec);
18008 break;
18009 case ALC880_MIC_EVENT:
18010 alc_mic_automute(codec);
18011 break;
18012 }
18013}
18014
18015#define alc663_mode7_setup alc663_mode1_setup
18016
18017static void alc663_mode7_inithook(struct hda_codec *codec)
18018{
18019 alc663_two_hp_m7_speaker_automute(codec);
18020 alc_mic_automute(codec);
18021}
18022
18023/* ***************** Mode8 ******************************/
18024static void alc663_mode8_unsol_event(struct hda_codec *codec,
18025 unsigned int res)
18026{
18027 switch (res >> 26) {
18028 case ALC880_HP_EVENT:
18029 alc663_two_hp_m8_speaker_automute(codec);
18030 break;
18031 case ALC880_MIC_EVENT:
18032 alc_mic_automute(codec);
18033 break;
18034 }
18035}
18036
18037#define alc663_mode8_setup alc663_m51va_setup
18038
18039static void alc663_mode8_inithook(struct hda_codec *codec)
18040{
18041 alc663_two_hp_m8_speaker_automute(codec);
18042 alc_mic_automute(codec);
18043}
18044
Kailang Yang6dda9f42008-05-27 12:05:31 +020018045static void alc663_g71v_hp_automute(struct hda_codec *codec)
18046{
18047 unsigned int present;
18048 unsigned char bits;
18049
Wu Fengguang864f92b2009-11-18 12:38:02 +080018050 present = snd_hda_jack_detect(codec, 0x21);
Kailang Yang6dda9f42008-05-27 12:05:31 +020018051 bits = present ? HDA_AMP_MUTE : 0;
18052 snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
18053 HDA_AMP_MUTE, bits);
18054 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
18055 HDA_AMP_MUTE, bits);
18056}
18057
18058static void alc663_g71v_front_automute(struct hda_codec *codec)
18059{
18060 unsigned int present;
18061 unsigned char bits;
18062
Wu Fengguang864f92b2009-11-18 12:38:02 +080018063 present = snd_hda_jack_detect(codec, 0x15);
Kailang Yang6dda9f42008-05-27 12:05:31 +020018064 bits = present ? HDA_AMP_MUTE : 0;
18065 snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
18066 HDA_AMP_MUTE, bits);
18067}
18068
18069static void alc663_g71v_unsol_event(struct hda_codec *codec,
18070 unsigned int res)
18071{
18072 switch (res >> 26) {
18073 case ALC880_HP_EVENT:
18074 alc663_g71v_hp_automute(codec);
18075 break;
18076 case ALC880_FRONT_EVENT:
18077 alc663_g71v_front_automute(codec);
18078 break;
18079 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018080 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020018081 break;
18082 }
18083}
18084
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018085#define alc663_g71v_setup alc663_m51va_setup
18086
Kailang Yang6dda9f42008-05-27 12:05:31 +020018087static void alc663_g71v_inithook(struct hda_codec *codec)
18088{
18089 alc663_g71v_front_automute(codec);
18090 alc663_g71v_hp_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018091 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020018092}
18093
18094static void alc663_g50v_unsol_event(struct hda_codec *codec,
18095 unsigned int res)
18096{
18097 switch (res >> 26) {
18098 case ALC880_HP_EVENT:
18099 alc663_m51va_speaker_automute(codec);
18100 break;
18101 case ALC880_MIC_EVENT:
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018102 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020018103 break;
18104 }
18105}
18106
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018107#define alc663_g50v_setup alc663_m51va_setup
18108
Kailang Yang6dda9f42008-05-27 12:05:31 +020018109static void alc663_g50v_inithook(struct hda_codec *codec)
18110{
18111 alc663_m51va_speaker_automute(codec);
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018112 alc_mic_automute(codec);
Kailang Yang6dda9f42008-05-27 12:05:31 +020018113}
18114
Kailang Yangf1d4e282008-08-26 14:03:29 +020018115static struct snd_kcontrol_new alc662_ecs_mixer[] = {
18116 HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
Takashi Iwai42171c12009-05-08 14:11:43 +020018117 ALC262_HIPPO_MASTER_SWITCH,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018118
18119 HDA_CODEC_VOLUME("e-Mic/LineIn Boost", 0x18, 0, HDA_INPUT),
18120 HDA_CODEC_VOLUME("e-Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
18121 HDA_CODEC_MUTE("e-Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT),
18122
18123 HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT),
18124 HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
18125 HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
18126 { } /* end */
18127};
18128
Chris Pockelé9541ba12009-05-12 08:08:53 +020018129static struct snd_kcontrol_new alc272_nc10_mixer[] = {
18130 /* Master Playback automatically created from Speaker and Headphone */
18131 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
18132 HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
18133 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
18134 HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
18135
18136 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
18137 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
18138 HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
18139
18140 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
18141 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
18142 HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
18143 { } /* end */
18144};
18145
Takashi Iwaicb53c622007-08-10 17:21:45 +020018146#ifdef CONFIG_SND_HDA_POWER_SAVE
18147#define alc662_loopbacks alc880_loopbacks
18148#endif
18149
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018150
Sasha Alexandrdef319f2009-06-16 16:00:15 -040018151/* pcm configuration: identical with ALC880 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018152#define alc662_pcm_analog_playback alc880_pcm_analog_playback
18153#define alc662_pcm_analog_capture alc880_pcm_analog_capture
18154#define alc662_pcm_digital_playback alc880_pcm_digital_playback
18155#define alc662_pcm_digital_capture alc880_pcm_digital_capture
18156
18157/*
18158 * configuration and preset
18159 */
18160static const char *alc662_models[ALC662_MODEL_LAST] = {
18161 [ALC662_3ST_2ch_DIG] = "3stack-dig",
18162 [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
18163 [ALC662_3ST_6ch] = "3stack-6ch",
18164 [ALC662_5ST_DIG] = "6stack-dig",
18165 [ALC662_LENOVO_101E] = "lenovo-101e",
Takashi Iwaib995d762007-10-17 10:41:06 +020018166 [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
Kailang Yang8c427222008-01-10 13:03:59 +010018167 [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
Kailang Yangf1d4e282008-08-26 14:03:29 +020018168 [ALC662_ECS] = "ecs",
Kailang Yang6dda9f42008-05-27 12:05:31 +020018169 [ALC663_ASUS_M51VA] = "m51va",
18170 [ALC663_ASUS_G71V] = "g71v",
18171 [ALC663_ASUS_H13] = "h13",
18172 [ALC663_ASUS_G50V] = "g50v",
Kailang Yangf1d4e282008-08-26 14:03:29 +020018173 [ALC663_ASUS_MODE1] = "asus-mode1",
18174 [ALC662_ASUS_MODE2] = "asus-mode2",
18175 [ALC663_ASUS_MODE3] = "asus-mode3",
18176 [ALC663_ASUS_MODE4] = "asus-mode4",
18177 [ALC663_ASUS_MODE5] = "asus-mode5",
18178 [ALC663_ASUS_MODE6] = "asus-mode6",
Kailang Yangebb83ee2009-12-17 12:23:00 +010018179 [ALC663_ASUS_MODE7] = "asus-mode7",
18180 [ALC663_ASUS_MODE8] = "asus-mode8",
Takashi Iwai01f2bd42009-05-11 08:12:43 +020018181 [ALC272_DELL] = "dell",
18182 [ALC272_DELL_ZM1] = "dell-zm1",
Chris Pockelé9541ba12009-05-12 08:08:53 +020018183 [ALC272_SAMSUNG_NC10] = "samsung-nc10",
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018184 [ALC662_AUTO] = "auto",
18185};
18186
18187static struct snd_pci_quirk alc662_cfg_tbl[] = {
Takashi Iwaidea0a502009-02-09 17:14:52 +010018188 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
Kailang Yang622e84c2009-04-21 07:39:04 +020018189 SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
18190 SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018191 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
18192 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
Kailang Yangcec27c82010-02-04 14:18:18 +010018193 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018194 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
18195 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
18196 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
18197 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
Kailang Yangebb83ee2009-12-17 12:23:00 +010018198 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
18199 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018200 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010018201 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
18202 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
18203 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
18204 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
18205 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018206 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010018207 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
18208 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018209 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
18210 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
18211 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
18212 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yangebb83ee2009-12-17 12:23:00 +010018213 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
Kailang Yang622e84c2009-04-21 07:39:04 +020018214 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
18215 SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
18216 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018217 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
18218 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
18219 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
18220 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020018221 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018222 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
18223 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
Kailang Yang6dda9f42008-05-27 12:05:31 +020018224 SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018225 /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
18226 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
18227 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
Kailang Yang622e84c2009-04-21 07:39:04 +020018228 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
Kailang Yangcec27c82010-02-04 14:18:18 +010018229 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
Kailang Yang622e84c2009-04-21 07:39:04 +020018230 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
18231 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018232 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
18233 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
18234 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020018235 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018236 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
18237 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
Kailang Yang622e84c2009-04-21 07:39:04 +020018238 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018239 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
Kailang Yang80ffe862008-10-15 11:23:27 +020018240 SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018241 /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
18242 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
18243 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
Kailang Yang622e84c2009-04-21 07:39:04 +020018244 SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018245 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
18246 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
Herton Ronaldo Krzesinski3da23ca2008-03-14 12:52:59 +010018247 SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
Kailang Yang291702f2007-10-16 14:28:03 +020018248 SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
Kailang Yang8c427222008-01-10 13:03:59 +010018249 SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018250 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
Herton Ronaldo Krzesinski95fe5f22008-09-26 23:48:45 -030018251 SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
18252 ALC662_3ST_6ch_DIG),
Takashi Iwai4dee8ba2010-01-13 17:20:08 +010018253 SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
Chris Pockelé9541ba12009-05-12 08:08:53 +020018254 SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
Herton Ronaldo Krzesinskicb559742008-09-26 23:47:45 -030018255 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
18256 ALC662_3ST_6ch_DIG),
Kailang Yang6227cdc2010-02-25 08:36:52 +010018257 SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
Vedran Miletic19c009a2008-09-29 20:29:25 +020018258 SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
Takashi Iwai5bd37292009-04-21 18:36:30 +020018259 SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018260 SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
Takashi Iwai238713d2008-10-05 10:57:39 +020018261 SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
Vedran Miletic19c009a2008-09-29 20:29:25 +020018262 ALC662_3ST_6ch_DIG),
Takashi Iwaidea0a502009-02-09 17:14:52 +010018263 SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
18264 ALC663_ASUS_H13),
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018265 {}
18266};
18267
18268static struct alc_config_preset alc662_presets[] = {
18269 [ALC662_3ST_2ch_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018270 .mixers = { alc662_3ST_2ch_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018271 .init_verbs = { alc662_init_verbs },
18272 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18273 .dac_nids = alc662_dac_nids,
18274 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018275 .dig_in_nid = ALC662_DIGIN_NID,
18276 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18277 .channel_mode = alc662_3ST_2ch_modes,
18278 .input_mux = &alc662_capture_source,
18279 },
18280 [ALC662_3ST_6ch_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018281 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018282 .init_verbs = { alc662_init_verbs },
18283 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18284 .dac_nids = alc662_dac_nids,
18285 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018286 .dig_in_nid = ALC662_DIGIN_NID,
18287 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18288 .channel_mode = alc662_3ST_6ch_modes,
18289 .need_dac_fix = 1,
18290 .input_mux = &alc662_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018291 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018292 [ALC662_3ST_6ch] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018293 .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018294 .init_verbs = { alc662_init_verbs },
18295 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18296 .dac_nids = alc662_dac_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018297 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18298 .channel_mode = alc662_3ST_6ch_modes,
18299 .need_dac_fix = 1,
18300 .input_mux = &alc662_capture_source,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018301 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018302 [ALC662_5ST_DIG] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018303 .mixers = { alc662_base_mixer, alc662_chmode_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018304 .init_verbs = { alc662_init_verbs },
18305 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18306 .dac_nids = alc662_dac_nids,
18307 .dig_out_nid = ALC662_DIGOUT_NID,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018308 .dig_in_nid = ALC662_DIGIN_NID,
18309 .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
18310 .channel_mode = alc662_5stack_modes,
18311 .input_mux = &alc662_capture_source,
18312 },
18313 [ALC662_LENOVO_101E] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018314 .mixers = { alc662_lenovo_101e_mixer },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018315 .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
18316 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18317 .dac_nids = alc662_dac_nids,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018318 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18319 .channel_mode = alc662_3ST_2ch_modes,
18320 .input_mux = &alc662_lenovo_101e_capture_source,
18321 .unsol_event = alc662_lenovo_101e_unsol_event,
18322 .init_hook = alc662_lenovo_101e_all_automute,
18323 },
Kailang Yang291702f2007-10-16 14:28:03 +020018324 [ALC662_ASUS_EEEPC_P701] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018325 .mixers = { alc662_eeepc_p701_mixer },
Kailang Yang291702f2007-10-16 14:28:03 +020018326 .init_verbs = { alc662_init_verbs,
18327 alc662_eeepc_sue_init_verbs },
18328 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18329 .dac_nids = alc662_dac_nids,
Kailang Yang291702f2007-10-16 14:28:03 +020018330 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18331 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang291702f2007-10-16 14:28:03 +020018332 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018333 .setup = alc662_eeepc_setup,
Kailang Yang291702f2007-10-16 14:28:03 +020018334 .init_hook = alc662_eeepc_inithook,
18335 },
Kailang Yang8c427222008-01-10 13:03:59 +010018336 [ALC662_ASUS_EEEPC_EP20] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018337 .mixers = { alc662_eeepc_ep20_mixer,
Kailang Yang8c427222008-01-10 13:03:59 +010018338 alc662_chmode_mixer },
18339 .init_verbs = { alc662_init_verbs,
18340 alc662_eeepc_ep20_sue_init_verbs },
18341 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18342 .dac_nids = alc662_dac_nids,
Kailang Yang8c427222008-01-10 13:03:59 +010018343 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18344 .channel_mode = alc662_3ST_6ch_modes,
18345 .input_mux = &alc662_lenovo_101e_capture_source,
Takashi Iwai42171c12009-05-08 14:11:43 +020018346 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018347 .setup = alc662_eeepc_ep20_setup,
Kailang Yang8c427222008-01-10 13:03:59 +010018348 .init_hook = alc662_eeepc_ep20_inithook,
18349 },
Kailang Yangf1d4e282008-08-26 14:03:29 +020018350 [ALC662_ECS] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018351 .mixers = { alc662_ecs_mixer },
Kailang Yangf1d4e282008-08-26 14:03:29 +020018352 .init_verbs = { alc662_init_verbs,
18353 alc662_ecs_init_verbs },
18354 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18355 .dac_nids = alc662_dac_nids,
18356 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18357 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018358 .unsol_event = alc662_eeepc_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018359 .setup = alc662_eeepc_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018360 .init_hook = alc662_eeepc_inithook,
18361 },
Kailang Yang6dda9f42008-05-27 12:05:31 +020018362 [ALC663_ASUS_M51VA] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018363 .mixers = { alc663_m51va_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020018364 .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
18365 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18366 .dac_nids = alc662_dac_nids,
18367 .dig_out_nid = ALC662_DIGOUT_NID,
18368 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18369 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020018370 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018371 .setup = alc663_m51va_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020018372 .init_hook = alc663_m51va_inithook,
18373 },
18374 [ALC663_ASUS_G71V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018375 .mixers = { alc663_g71v_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020018376 .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
18377 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18378 .dac_nids = alc662_dac_nids,
18379 .dig_out_nid = ALC662_DIGOUT_NID,
18380 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18381 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020018382 .unsol_event = alc663_g71v_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018383 .setup = alc663_g71v_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020018384 .init_hook = alc663_g71v_inithook,
18385 },
18386 [ALC663_ASUS_H13] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018387 .mixers = { alc663_m51va_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020018388 .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
18389 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18390 .dac_nids = alc662_dac_nids,
18391 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18392 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang6dda9f42008-05-27 12:05:31 +020018393 .unsol_event = alc663_m51va_unsol_event,
18394 .init_hook = alc663_m51va_inithook,
18395 },
18396 [ALC663_ASUS_G50V] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018397 .mixers = { alc663_g50v_mixer },
Kailang Yang6dda9f42008-05-27 12:05:31 +020018398 .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
18399 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18400 .dac_nids = alc662_dac_nids,
18401 .dig_out_nid = ALC662_DIGOUT_NID,
18402 .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
18403 .channel_mode = alc662_3ST_6ch_modes,
18404 .input_mux = &alc663_capture_source,
18405 .unsol_event = alc663_g50v_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018406 .setup = alc663_g50v_setup,
Kailang Yang6dda9f42008-05-27 12:05:31 +020018407 .init_hook = alc663_g50v_inithook,
18408 },
Kailang Yangf1d4e282008-08-26 14:03:29 +020018409 [ALC663_ASUS_MODE1] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018410 .mixers = { alc663_m51va_mixer },
18411 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018412 .init_verbs = { alc662_init_verbs,
18413 alc663_21jd_amic_init_verbs },
18414 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18415 .hp_nid = 0x03,
18416 .dac_nids = alc662_dac_nids,
18417 .dig_out_nid = ALC662_DIGOUT_NID,
18418 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18419 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018420 .unsol_event = alc663_mode1_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018421 .setup = alc663_mode1_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018422 .init_hook = alc663_mode1_inithook,
18423 },
18424 [ALC662_ASUS_MODE2] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018425 .mixers = { alc662_1bjd_mixer },
18426 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018427 .init_verbs = { alc662_init_verbs,
18428 alc662_1bjd_amic_init_verbs },
18429 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18430 .dac_nids = alc662_dac_nids,
18431 .dig_out_nid = ALC662_DIGOUT_NID,
18432 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18433 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018434 .unsol_event = alc662_mode2_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018435 .setup = alc662_mode2_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018436 .init_hook = alc662_mode2_inithook,
18437 },
18438 [ALC663_ASUS_MODE3] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018439 .mixers = { alc663_two_hp_m1_mixer },
18440 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018441 .init_verbs = { alc662_init_verbs,
18442 alc663_two_hp_amic_m1_init_verbs },
18443 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18444 .hp_nid = 0x03,
18445 .dac_nids = alc662_dac_nids,
18446 .dig_out_nid = ALC662_DIGOUT_NID,
18447 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18448 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018449 .unsol_event = alc663_mode3_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018450 .setup = alc663_mode3_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018451 .init_hook = alc663_mode3_inithook,
18452 },
18453 [ALC663_ASUS_MODE4] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018454 .mixers = { alc663_asus_21jd_clfe_mixer },
18455 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018456 .init_verbs = { alc662_init_verbs,
18457 alc663_21jd_amic_init_verbs},
18458 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18459 .hp_nid = 0x03,
18460 .dac_nids = alc662_dac_nids,
18461 .dig_out_nid = ALC662_DIGOUT_NID,
18462 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18463 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018464 .unsol_event = alc663_mode4_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018465 .setup = alc663_mode4_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018466 .init_hook = alc663_mode4_inithook,
18467 },
18468 [ALC663_ASUS_MODE5] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018469 .mixers = { alc663_asus_15jd_clfe_mixer },
18470 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018471 .init_verbs = { alc662_init_verbs,
18472 alc663_15jd_amic_init_verbs },
18473 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18474 .hp_nid = 0x03,
18475 .dac_nids = alc662_dac_nids,
18476 .dig_out_nid = ALC662_DIGOUT_NID,
18477 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18478 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018479 .unsol_event = alc663_mode5_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018480 .setup = alc663_mode5_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018481 .init_hook = alc663_mode5_inithook,
18482 },
18483 [ALC663_ASUS_MODE6] = {
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018484 .mixers = { alc663_two_hp_m2_mixer },
18485 .cap_mixer = alc662_auto_capture_mixer,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018486 .init_verbs = { alc662_init_verbs,
18487 alc663_two_hp_amic_m2_init_verbs },
18488 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18489 .hp_nid = 0x03,
18490 .dac_nids = alc662_dac_nids,
18491 .dig_out_nid = ALC662_DIGOUT_NID,
18492 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18493 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018494 .unsol_event = alc663_mode6_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018495 .setup = alc663_mode6_setup,
Kailang Yangf1d4e282008-08-26 14:03:29 +020018496 .init_hook = alc663_mode6_inithook,
18497 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010018498 [ALC663_ASUS_MODE7] = {
18499 .mixers = { alc663_mode7_mixer },
18500 .cap_mixer = alc662_auto_capture_mixer,
18501 .init_verbs = { alc662_init_verbs,
18502 alc663_mode7_init_verbs },
18503 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18504 .hp_nid = 0x03,
18505 .dac_nids = alc662_dac_nids,
18506 .dig_out_nid = ALC662_DIGOUT_NID,
18507 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18508 .channel_mode = alc662_3ST_2ch_modes,
18509 .unsol_event = alc663_mode7_unsol_event,
18510 .setup = alc663_mode7_setup,
18511 .init_hook = alc663_mode7_inithook,
18512 },
18513 [ALC663_ASUS_MODE8] = {
18514 .mixers = { alc663_mode8_mixer },
18515 .cap_mixer = alc662_auto_capture_mixer,
18516 .init_verbs = { alc662_init_verbs,
18517 alc663_mode8_init_verbs },
18518 .num_dacs = ARRAY_SIZE(alc662_dac_nids),
18519 .hp_nid = 0x03,
18520 .dac_nids = alc662_dac_nids,
18521 .dig_out_nid = ALC662_DIGOUT_NID,
18522 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18523 .channel_mode = alc662_3ST_2ch_modes,
18524 .unsol_event = alc663_mode8_unsol_event,
18525 .setup = alc663_mode8_setup,
18526 .init_hook = alc663_mode8_inithook,
18527 },
Kailang Yang622e84c2009-04-21 07:39:04 +020018528 [ALC272_DELL] = {
18529 .mixers = { alc663_m51va_mixer },
18530 .cap_mixer = alc272_auto_capture_mixer,
18531 .init_verbs = { alc662_init_verbs, alc272_dell_init_verbs },
18532 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18533 .dac_nids = alc662_dac_nids,
18534 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18535 .adc_nids = alc272_adc_nids,
18536 .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
18537 .capsrc_nids = alc272_capsrc_nids,
18538 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang622e84c2009-04-21 07:39:04 +020018539 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018540 .setup = alc663_m51va_setup,
Kailang Yang622e84c2009-04-21 07:39:04 +020018541 .init_hook = alc663_m51va_inithook,
18542 },
18543 [ALC272_DELL_ZM1] = {
18544 .mixers = { alc663_m51va_mixer },
18545 .cap_mixer = alc662_auto_capture_mixer,
18546 .init_verbs = { alc662_init_verbs, alc272_dell_zm1_init_verbs },
18547 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18548 .dac_nids = alc662_dac_nids,
18549 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18550 .adc_nids = alc662_adc_nids,
Takashi Iwaib59bdf32009-08-11 09:47:30 +020018551 .num_adc_nids = 1,
Kailang Yang622e84c2009-04-21 07:39:04 +020018552 .capsrc_nids = alc662_capsrc_nids,
18553 .channel_mode = alc662_3ST_2ch_modes,
Kailang Yang622e84c2009-04-21 07:39:04 +020018554 .unsol_event = alc663_m51va_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018555 .setup = alc663_m51va_setup,
Kailang Yang622e84c2009-04-21 07:39:04 +020018556 .init_hook = alc663_m51va_inithook,
18557 },
Chris Pockelé9541ba12009-05-12 08:08:53 +020018558 [ALC272_SAMSUNG_NC10] = {
18559 .mixers = { alc272_nc10_mixer },
18560 .init_verbs = { alc662_init_verbs,
18561 alc663_21jd_amic_init_verbs },
18562 .num_dacs = ARRAY_SIZE(alc272_dac_nids),
18563 .dac_nids = alc272_dac_nids,
18564 .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
18565 .channel_mode = alc662_3ST_2ch_modes,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018566 /*.input_mux = &alc272_nc10_capture_source,*/
Chris Pockelé9541ba12009-05-12 08:08:53 +020018567 .unsol_event = alc663_mode4_unsol_event,
Takashi Iwai4f5d17062009-08-11 18:17:46 +020018568 .setup = alc663_mode4_setup,
Chris Pockelé9541ba12009-05-12 08:08:53 +020018569 .init_hook = alc663_mode4_inithook,
18570 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018571};
18572
18573
18574/*
18575 * BIOS auto configuration
18576 */
18577
Takashi Iwai7085ec12009-10-02 09:03:58 +020018578/* convert from MIX nid to DAC */
18579static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
18580{
18581 if (nid == 0x0f)
18582 return 0x02;
18583 else if (nid >= 0x0c && nid <= 0x0e)
18584 return nid - 0x0c + 0x02;
18585 else
18586 return 0;
18587}
18588
18589/* get MIX nid connected to the given pin targeted to DAC */
18590static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
18591 hda_nid_t dac)
18592{
18593 hda_nid_t mix[4];
18594 int i, num;
18595
18596 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
18597 for (i = 0; i < num; i++) {
18598 if (alc662_mix_to_dac(mix[i]) == dac)
18599 return mix[i];
18600 }
18601 return 0;
18602}
18603
18604/* look for an empty DAC slot */
18605static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
18606{
18607 struct alc_spec *spec = codec->spec;
18608 hda_nid_t srcs[5];
18609 int i, j, num;
18610
18611 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
18612 if (num < 0)
18613 return 0;
18614 for (i = 0; i < num; i++) {
18615 hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
18616 if (!nid)
18617 continue;
18618 for (j = 0; j < spec->multiout.num_dacs; j++)
18619 if (spec->multiout.dac_nids[j] == nid)
18620 break;
18621 if (j >= spec->multiout.num_dacs)
18622 return nid;
18623 }
18624 return 0;
18625}
18626
18627/* fill in the dac_nids table from the parsed pin configuration */
18628static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
18629 const struct auto_pin_cfg *cfg)
18630{
18631 struct alc_spec *spec = codec->spec;
18632 int i;
18633 hda_nid_t dac;
18634
18635 spec->multiout.dac_nids = spec->private_dac_nids;
18636 for (i = 0; i < cfg->line_outs; i++) {
18637 dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
18638 if (!dac)
18639 continue;
18640 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
18641 }
18642 return 0;
18643}
18644
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018645static inline int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018646 hda_nid_t nid, unsigned int chs)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018647{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018648 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018649 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
18650}
18651
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018652static inline int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018653 hda_nid_t nid, unsigned int chs)
18654{
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018655 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018656 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
18657}
18658
18659#define alc662_add_stereo_vol(spec, pfx, nid) \
18660 alc662_add_vol_ctl(spec, pfx, nid, 3)
18661#define alc662_add_stereo_sw(spec, pfx, nid) \
18662 alc662_add_sw_ctl(spec, pfx, nid, 3)
18663
18664/* add playback controls from the parsed DAC table */
18665static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
18666 const struct auto_pin_cfg *cfg)
18667{
18668 struct alc_spec *spec = codec->spec;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018669 static const char *chname[4] = {
18670 "Front", "Surround", NULL /*CLFE*/, "Side"
18671 };
Takashi Iwai7085ec12009-10-02 09:03:58 +020018672 hda_nid_t nid, mix;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018673 int i, err;
18674
18675 for (i = 0; i < cfg->line_outs; i++) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018676 nid = spec->multiout.dac_nids[i];
18677 if (!nid)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018678 continue;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018679 mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
18680 if (!mix)
18681 continue;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018682 if (i == 2) {
18683 /* Center/LFE */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018684 err = alc662_add_vol_ctl(spec, "Center", nid, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018685 if (err < 0)
18686 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018687 err = alc662_add_vol_ctl(spec, "LFE", nid, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018688 if (err < 0)
18689 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018690 err = alc662_add_sw_ctl(spec, "Center", mix, 1);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018691 if (err < 0)
18692 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018693 err = alc662_add_sw_ctl(spec, "LFE", mix, 2);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018694 if (err < 0)
18695 return err;
18696 } else {
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018697 const char *pfx;
18698 if (cfg->line_outs == 1 &&
18699 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018700 if (cfg->hp_outs)
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018701 pfx = "Speaker";
18702 else
18703 pfx = "PCM";
18704 } else
18705 pfx = chname[i];
Takashi Iwai7085ec12009-10-02 09:03:58 +020018706 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018707 if (err < 0)
18708 return err;
Takashi Iwai0d884cb2009-08-25 16:14:35 +020018709 if (cfg->line_outs == 1 &&
18710 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
18711 pfx = "Speaker";
Takashi Iwai7085ec12009-10-02 09:03:58 +020018712 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018713 if (err < 0)
18714 return err;
18715 }
18716 }
18717 return 0;
18718}
18719
18720/* add playback controls for speaker and HP outputs */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018721/* return DAC nid if any new DAC is assigned */
18722static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018723 const char *pfx)
18724{
Takashi Iwai7085ec12009-10-02 09:03:58 +020018725 struct alc_spec *spec = codec->spec;
18726 hda_nid_t nid, mix;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018727 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018728
18729 if (!pin)
18730 return 0;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018731 nid = alc662_look_for_dac(codec, pin);
18732 if (!nid) {
Takashi Iwai7085ec12009-10-02 09:03:58 +020018733 /* the corresponding DAC is already occupied */
18734 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
18735 return 0; /* no way */
18736 /* create a switch only */
Takashi Iwai0afe5f82009-10-02 09:20:00 +020018737 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018738 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
18739 }
18740
18741 mix = alc662_dac_to_mix(codec, pin, nid);
18742 if (!mix)
18743 return 0;
18744 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
18745 if (err < 0)
Takashi Iwai24fb9172008-09-02 14:48:20 +020018746 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018747 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
18748 if (err < 0)
18749 return err;
18750 return nid;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018751}
18752
18753/* create playback/capture controls for input pins */
Takashi Iwai05f5f472009-08-25 13:10:18 +020018754#define alc662_auto_create_input_ctls \
Takashi Iwai4b7348a2009-10-14 18:25:23 +020018755 alc882_auto_create_input_ctls
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018756
18757static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
18758 hda_nid_t nid, int pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018759 hda_nid_t dac)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018760{
Takashi Iwai7085ec12009-10-02 09:03:58 +020018761 int i, num;
Takashi Iwaice503f32010-07-30 10:37:29 +020018762 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
Takashi Iwai7085ec12009-10-02 09:03:58 +020018763
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018764 alc_set_pin_output(codec, nid, pin_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018765 /* need the manual connection? */
Takashi Iwai7085ec12009-10-02 09:03:58 +020018766 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
18767 if (num <= 1)
18768 return;
18769 for (i = 0; i < num; i++) {
18770 if (alc662_mix_to_dac(srcs[i]) != dac)
18771 continue;
18772 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
18773 return;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018774 }
18775}
18776
18777static void alc662_auto_init_multi_out(struct hda_codec *codec)
18778{
18779 struct alc_spec *spec = codec->spec;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018780 int pin_type = get_pin_type(spec->autocfg.line_out_type);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018781 int i;
18782
18783 for (i = 0; i <= HDA_SIDE; i++) {
18784 hda_nid_t nid = spec->autocfg.line_out_pins[i];
18785 if (nid)
Takashi Iwaibaba8ee2007-04-23 17:17:48 +020018786 alc662_auto_set_output_and_unmute(codec, nid, pin_type,
Takashi Iwai7085ec12009-10-02 09:03:58 +020018787 spec->multiout.dac_nids[i]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018788 }
18789}
18790
18791static void alc662_auto_init_hp_out(struct hda_codec *codec)
18792{
18793 struct alc_spec *spec = codec->spec;
18794 hda_nid_t pin;
18795
18796 pin = spec->autocfg.hp_pins[0];
Takashi Iwai7085ec12009-10-02 09:03:58 +020018797 if (pin)
18798 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
18799 spec->multiout.hp_nid);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018800 pin = spec->autocfg.speaker_pins[0];
18801 if (pin)
Takashi Iwai7085ec12009-10-02 09:03:58 +020018802 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
18803 spec->multiout.extra_out_nid[0]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018804}
18805
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018806#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
18807
18808static void alc662_auto_init_analog_input(struct hda_codec *codec)
18809{
18810 struct alc_spec *spec = codec->spec;
Takashi Iwai66ceeb62010-08-30 13:05:52 +020018811 struct auto_pin_cfg *cfg = &spec->autocfg;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018812 int i;
18813
Takashi Iwai66ceeb62010-08-30 13:05:52 +020018814 for (i = 0; i < cfg->num_inputs; i++) {
18815 hda_nid_t nid = cfg->inputs[i].pin;
Takashi Iwai05f5f472009-08-25 13:10:18 +020018816 if (alc_is_input_pin(codec, nid)) {
Takashi Iwai23f0c042009-02-26 13:03:58 +010018817 alc_set_input_pin(codec, nid, i);
Takashi Iwai52ca15b2009-03-23 12:51:55 +010018818 if (nid != ALC662_PIN_CD_NID &&
Takashi Iwaie82c0252009-03-23 15:17:38 +010018819 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018820 snd_hda_codec_write(codec, nid, 0,
18821 AC_VERB_SET_AMP_GAIN_MUTE,
18822 AMP_OUT_MUTE);
18823 }
18824 }
18825}
18826
Takashi Iwaif511b012008-08-15 16:46:42 +020018827#define alc662_auto_init_input_src alc882_auto_init_input_src
18828
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018829static int alc662_parse_auto_config(struct hda_codec *codec)
18830{
18831 struct alc_spec *spec = codec->spec;
18832 int err;
18833 static hda_nid_t alc662_ignore[] = { 0x1d, 0 };
18834
18835 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
18836 alc662_ignore);
18837 if (err < 0)
18838 return err;
18839 if (!spec->autocfg.line_outs)
18840 return 0; /* can't find valid BIOS pin config */
18841
Takashi Iwai7085ec12009-10-02 09:03:58 +020018842 err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018843 if (err < 0)
18844 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018845 err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018846 if (err < 0)
18847 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018848 err = alc662_auto_create_extra_out(codec,
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018849 spec->autocfg.speaker_pins[0],
18850 "Speaker");
18851 if (err < 0)
18852 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018853 if (err)
18854 spec->multiout.extra_out_nid[0] = err;
18855 err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018856 "Headphone");
18857 if (err < 0)
18858 return err;
Takashi Iwai7085ec12009-10-02 09:03:58 +020018859 if (err)
18860 spec->multiout.hp_nid = err;
Takashi Iwai05f5f472009-08-25 13:10:18 +020018861 err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
Takashi Iwaif12ab1e2007-04-12 15:51:47 +020018862 if (err < 0)
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018863 return err;
18864
18865 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
18866
Takashi Iwai757899a2010-07-30 10:48:14 +020018867 alc_auto_parse_digital(codec);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018868
Takashi Iwai603c4012008-07-30 15:01:44 +020018869 if (spec->kctls.list)
Takashi Iwaid88897e2008-10-31 15:01:37 +010018870 add_mixer(spec, spec->kctls.list);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018871
18872 spec->num_mux_defs = 1;
Herton Ronaldo Krzesinski61b9b9b2009-01-28 09:16:33 -020018873 spec->input_mux = &spec->private_imux[0];
Kailang Yangea1fb292008-08-26 12:58:38 +020018874
Kailang Yangcec27c82010-02-04 14:18:18 +010018875 add_verb(spec, alc662_init_verbs);
18876 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
Kailang Yangd1eb57f2010-06-23 16:25:26 +020018877 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
Kailang Yangcec27c82010-02-04 14:18:18 +010018878 add_verb(spec, alc663_init_verbs);
18879
18880 if (codec->vendor_id == 0x10ec0272)
18881 add_verb(spec, alc272_init_verbs);
Takashi Iwaiee979a142008-09-02 15:42:20 +020018882
18883 err = alc_auto_add_mic_boost(codec);
18884 if (err < 0)
18885 return err;
18886
Kailang Yang6227cdc2010-02-25 08:36:52 +010018887 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
18888 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
18889 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
18890 else
18891 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
Takashi Iwai4a79ba32009-04-22 16:31:35 +020018892
Takashi Iwai8c872862007-06-19 12:11:16 +020018893 return 1;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018894}
18895
18896/* additional initialization for auto-configuration model */
18897static void alc662_auto_init(struct hda_codec *codec)
18898{
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018899 struct alc_spec *spec = codec->spec;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018900 alc662_auto_init_multi_out(codec);
18901 alc662_auto_init_hp_out(codec);
18902 alc662_auto_init_analog_input(codec);
Takashi Iwaif511b012008-08-15 16:46:42 +020018903 alc662_auto_init_input_src(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +020018904 alc_auto_init_digital(codec);
Takashi Iwaif6c7e542008-02-12 18:32:23 +010018905 if (spec->unsol_event)
Kailang Yang7fb0d782008-10-15 11:12:35 +020018906 alc_inithook(codec);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018907}
18908
18909static int patch_alc662(struct hda_codec *codec)
18910{
18911 struct alc_spec *spec;
18912 int err, board_config;
18913
18914 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
18915 if (!spec)
18916 return -ENOMEM;
18917
18918 codec->spec = spec;
18919
Kailang Yangda00c242010-03-19 11:23:45 +010018920 alc_auto_parse_customize_define(codec);
18921
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +020018922 alc_fix_pll_init(codec, 0x20, 0x04, 15);
18923
Kailang Yangc027ddc2010-03-19 11:33:06 +010018924 if (alc_read_coef_idx(codec, 0) == 0x8020)
18925 alc_codec_rename(codec, "ALC661");
18926 else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) &&
18927 codec->bus->pci->subsystem_vendor == 0x1025 &&
18928 spec->cdefine.platform_type == 1)
18929 alc_codec_rename(codec, "ALC272X");
Kailang Yang274693f2009-12-03 10:07:50 +010018930
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018931 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
18932 alc662_models,
18933 alc662_cfg_tbl);
18934 if (board_config < 0) {
Takashi Iwai9a11f1a2009-07-28 16:01:20 +020018935 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
18936 codec->chip_name);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018937 board_config = ALC662_AUTO;
18938 }
18939
18940 if (board_config == ALC662_AUTO) {
18941 /* automatic parse from the BIOS config */
18942 err = alc662_parse_auto_config(codec);
18943 if (err < 0) {
18944 alc_free(codec);
18945 return err;
Takashi Iwai8c872862007-06-19 12:11:16 +020018946 } else if (!err) {
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018947 printk(KERN_INFO
18948 "hda_codec: Cannot set up configuration "
18949 "from BIOS. Using base mode...\n");
18950 board_config = ALC662_3ST_2ch_DIG;
18951 }
18952 }
18953
Takashi Iwaidc1eae22010-07-29 15:30:02 +020018954 if (has_cdefine_beep(codec)) {
Takashi Iwai8af25912010-07-28 17:37:16 +020018955 err = snd_hda_attach_beep_device(codec, 0x1);
18956 if (err < 0) {
18957 alc_free(codec);
18958 return err;
18959 }
Kusanagi Kouichi680cd532009-02-05 00:00:58 +090018960 }
18961
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018962 if (board_config != ALC662_AUTO)
Takashi Iwaie9c364c2009-08-11 17:16:13 +020018963 setup_preset(codec, &alc662_presets[board_config]);
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018964
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018965 spec->stream_analog_playback = &alc662_pcm_analog_playback;
18966 spec->stream_analog_capture = &alc662_pcm_analog_capture;
18967
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018968 spec->stream_digital_playback = &alc662_pcm_digital_playback;
18969 spec->stream_digital_capture = &alc662_pcm_digital_capture;
18970
Takashi Iwaidd704692009-08-11 08:45:11 +020018971 if (!spec->adc_nids) {
18972 spec->adc_nids = alc662_adc_nids;
18973 spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
18974 }
18975 if (!spec->capsrc_nids)
18976 spec->capsrc_nids = alc662_capsrc_nids;
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018977
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018978 if (!spec->cap_mixer)
Takashi Iwaib59bdf32009-08-11 09:47:30 +020018979 set_capture_mixer(codec);
Takashi Iwaif9e336f2008-10-31 16:37:07 +010018980
Takashi Iwaidc1eae22010-07-29 15:30:02 +020018981 if (has_cdefine_beep(codec)) {
Kailang Yangda00c242010-03-19 11:23:45 +010018982 switch (codec->vendor_id) {
18983 case 0x10ec0662:
18984 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
18985 break;
18986 case 0x10ec0272:
18987 case 0x10ec0663:
18988 case 0x10ec0665:
18989 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
18990 break;
18991 case 0x10ec0273:
18992 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
18993 break;
18994 }
Kailang Yangcec27c82010-02-04 14:18:18 +010018995 }
Takashi Iwai2134ea42008-01-10 16:53:55 +010018996 spec->vmaster_nid = 0x02;
18997
Kailang Yangbc9f98a2007-04-12 13:06:07 +020018998 codec->patch_ops = alc_patch_ops;
18999 if (board_config == ALC662_AUTO)
19000 spec->init_hook = alc662_auto_init;
Takashi Iwaicb53c622007-08-10 17:21:45 +020019001#ifdef CONFIG_SND_HDA_POWER_SAVE
19002 if (!spec->loopback.amplist)
19003 spec->loopback.amplist = alc662_loopbacks;
19004#endif
Kailang Yangbc9f98a2007-04-12 13:06:07 +020019005
19006 return 0;
19007}
19008
Kailang Yang274693f2009-12-03 10:07:50 +010019009static int patch_alc888(struct hda_codec *codec)
19010{
19011 if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
19012 kfree(codec->chip_name);
19013 codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010019014 if (!codec->chip_name) {
19015 alc_free(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010019016 return -ENOMEM;
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010019017 }
19018 return patch_alc662(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010019019 }
Takashi Iwaiac2c92e2009-12-03 10:14:10 +010019020 return patch_alc882(codec);
Kailang Yang274693f2009-12-03 10:07:50 +010019021}
19022
Kailang Yangbc9f98a2007-04-12 13:06:07 +020019023/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019024 * ALC680 support
19025 */
Kailang Yangc69aefa2010-08-17 10:39:22 +020019026#define ALC680_DIGIN_NID ALC880_DIGIN_NID
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019027#define ALC680_DIGOUT_NID ALC880_DIGOUT_NID
19028#define alc680_modes alc260_modes
19029
19030static hda_nid_t alc680_dac_nids[3] = {
19031 /* Lout1, Lout2, hp */
19032 0x02, 0x03, 0x04
19033};
19034
19035static hda_nid_t alc680_adc_nids[3] = {
19036 /* ADC0-2 */
19037 /* DMIC, MIC, Line-in*/
19038 0x07, 0x08, 0x09
19039};
19040
Kailang Yangc69aefa2010-08-17 10:39:22 +020019041/*
19042 * Analog capture ADC cgange
19043 */
Takashi Iwai66ceeb62010-08-30 13:05:52 +020019044static void alc680_rec_autoswitch(struct hda_codec *codec)
19045{
19046 struct alc_spec *spec = codec->spec;
19047 struct auto_pin_cfg *cfg = &spec->autocfg;
19048 int pin_found = 0;
19049 int type_found = AUTO_PIN_LAST;
19050 hda_nid_t nid;
19051 int i;
19052
19053 for (i = 0; i < cfg->num_inputs; i++) {
19054 nid = cfg->inputs[i].pin;
19055 if (!(snd_hda_query_pin_caps(codec, nid) &
19056 AC_PINCAP_PRES_DETECT))
19057 continue;
19058 if (snd_hda_jack_detect(codec, nid)) {
19059 if (cfg->inputs[i].type < type_found) {
19060 type_found = cfg->inputs[i].type;
19061 pin_found = nid;
19062 }
19063 }
19064 }
19065
19066 nid = 0x07;
19067 if (pin_found)
19068 snd_hda_get_connections(codec, pin_found, &nid, 1);
19069
19070 if (nid != spec->cur_adc)
19071 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
19072 spec->cur_adc = nid;
19073 snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0,
19074 spec->cur_adc_format);
19075}
19076
Kailang Yangc69aefa2010-08-17 10:39:22 +020019077static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
19078 struct hda_codec *codec,
19079 unsigned int stream_tag,
19080 unsigned int format,
19081 struct snd_pcm_substream *substream)
19082{
19083 struct alc_spec *spec = codec->spec;
Kailang Yangc69aefa2010-08-17 10:39:22 +020019084
Takashi Iwai66ceeb62010-08-30 13:05:52 +020019085 spec->cur_adc = 0x07;
Kailang Yangc69aefa2010-08-17 10:39:22 +020019086 spec->cur_adc_stream_tag = stream_tag;
19087 spec->cur_adc_format = format;
19088
Takashi Iwai66ceeb62010-08-30 13:05:52 +020019089 alc680_rec_autoswitch(codec);
Kailang Yangc69aefa2010-08-17 10:39:22 +020019090 return 0;
19091}
19092
19093static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
19094 struct hda_codec *codec,
19095 struct snd_pcm_substream *substream)
19096{
19097 snd_hda_codec_cleanup_stream(codec, 0x07);
19098 snd_hda_codec_cleanup_stream(codec, 0x08);
19099 snd_hda_codec_cleanup_stream(codec, 0x09);
19100 return 0;
19101}
19102
19103static struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
19104 .substreams = 1, /* can be overridden */
19105 .channels_min = 2,
19106 .channels_max = 2,
19107 /* NID is set in alc_build_pcms */
19108 .ops = {
19109 .prepare = alc680_capture_pcm_prepare,
19110 .cleanup = alc680_capture_pcm_cleanup
19111 },
19112};
19113
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019114static struct snd_kcontrol_new alc680_base_mixer[] = {
19115 /* output mixer control */
19116 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
19117 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
19118 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
19119 HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
Kailang Yangc69aefa2010-08-17 10:39:22 +020019120 HDA_CODEC_VOLUME("Int Mic Boost", 0x12, 0, HDA_INPUT),
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019121 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
Kailang Yangc69aefa2010-08-17 10:39:22 +020019122 HDA_CODEC_VOLUME("Line In Boost", 0x19, 0, HDA_INPUT),
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019123 { }
19124};
19125
Kailang Yangc69aefa2010-08-17 10:39:22 +020019126static struct hda_bind_ctls alc680_bind_cap_vol = {
19127 .ops = &snd_hda_bind_vol,
19128 .values = {
19129 HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
19130 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
19131 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
19132 0
19133 },
19134};
19135
19136static struct hda_bind_ctls alc680_bind_cap_switch = {
19137 .ops = &snd_hda_bind_sw,
19138 .values = {
19139 HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
19140 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
19141 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
19142 0
19143 },
19144};
19145
19146static struct snd_kcontrol_new alc680_master_capture_mixer[] = {
19147 HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
19148 HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019149 { } /* end */
19150};
19151
19152/*
19153 * generic initialization of ADC, input mixers and output mixers
19154 */
19155static struct hda_verb alc680_init_verbs[] = {
Kailang Yangc69aefa2010-08-17 10:39:22 +020019156 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
19157 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
19158 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019159
Kailang Yangc69aefa2010-08-17 10:39:22 +020019160 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
19161 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
19162 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
19163 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
19164 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
19165 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019166
19167 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19168 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19169 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19170 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19171 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
Kailang Yangc69aefa2010-08-17 10:39:22 +020019172
19173 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
19174 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
Takashi Iwai66ceeb62010-08-30 13:05:52 +020019175 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
Kailang Yangc69aefa2010-08-17 10:39:22 +020019176
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019177 { }
19178};
19179
Kailang Yangc69aefa2010-08-17 10:39:22 +020019180/* toggle speaker-output according to the hp-jack state */
19181static void alc680_base_setup(struct hda_codec *codec)
19182{
19183 struct alc_spec *spec = codec->spec;
19184
19185 spec->autocfg.hp_pins[0] = 0x16;
19186 spec->autocfg.speaker_pins[0] = 0x14;
19187 spec->autocfg.speaker_pins[1] = 0x15;
Takashi Iwai66ceeb62010-08-30 13:05:52 +020019188 spec->autocfg.num_inputs = 2;
19189 spec->autocfg.inputs[0].pin = 0x18;
19190 spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
19191 spec->autocfg.inputs[1].pin = 0x19;
19192 spec->autocfg.inputs[1].type = AUTO_PIN_LINE;
Kailang Yangc69aefa2010-08-17 10:39:22 +020019193}
19194
19195static void alc680_unsol_event(struct hda_codec *codec,
19196 unsigned int res)
19197{
19198 if ((res >> 26) == ALC880_HP_EVENT)
19199 alc_automute_amp(codec);
19200 if ((res >> 26) == ALC880_MIC_EVENT)
19201 alc680_rec_autoswitch(codec);
19202}
19203
19204static void alc680_inithook(struct hda_codec *codec)
19205{
19206 alc_automute_amp(codec);
19207 alc680_rec_autoswitch(codec);
19208}
19209
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019210/* create input playback/capture controls for the given pin */
19211static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
19212 const char *ctlname, int idx)
19213{
19214 hda_nid_t dac;
19215 int err;
19216
19217 switch (nid) {
19218 case 0x14:
19219 dac = 0x02;
19220 break;
19221 case 0x15:
19222 dac = 0x03;
19223 break;
19224 case 0x16:
19225 dac = 0x04;
19226 break;
19227 default:
19228 return 0;
19229 }
19230 if (spec->multiout.dac_nids[0] != dac &&
19231 spec->multiout.dac_nids[1] != dac) {
19232 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
19233 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
19234 HDA_OUTPUT));
19235 if (err < 0)
19236 return err;
19237
19238 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
19239 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
19240
19241 if (err < 0)
19242 return err;
19243 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
19244 }
19245
19246 return 0;
19247}
19248
19249/* add playback controls from the parsed DAC table */
19250static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec,
19251 const struct auto_pin_cfg *cfg)
19252{
19253 hda_nid_t nid;
19254 int err;
19255
19256 spec->multiout.dac_nids = spec->private_dac_nids;
19257
19258 nid = cfg->line_out_pins[0];
19259 if (nid) {
19260 const char *name;
19261 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
19262 name = "Speaker";
19263 else
19264 name = "Front";
19265 err = alc680_new_analog_output(spec, nid, name, 0);
19266 if (err < 0)
19267 return err;
19268 }
19269
19270 nid = cfg->speaker_pins[0];
19271 if (nid) {
19272 err = alc680_new_analog_output(spec, nid, "Speaker", 0);
19273 if (err < 0)
19274 return err;
19275 }
19276 nid = cfg->hp_pins[0];
19277 if (nid) {
19278 err = alc680_new_analog_output(spec, nid, "Headphone", 0);
19279 if (err < 0)
19280 return err;
19281 }
19282
19283 return 0;
19284}
19285
19286static void alc680_auto_set_output_and_unmute(struct hda_codec *codec,
19287 hda_nid_t nid, int pin_type)
19288{
19289 alc_set_pin_output(codec, nid, pin_type);
19290}
19291
19292static void alc680_auto_init_multi_out(struct hda_codec *codec)
19293{
19294 struct alc_spec *spec = codec->spec;
19295 hda_nid_t nid = spec->autocfg.line_out_pins[0];
19296 if (nid) {
19297 int pin_type = get_pin_type(spec->autocfg.line_out_type);
19298 alc680_auto_set_output_and_unmute(codec, nid, pin_type);
19299 }
19300}
19301
19302static void alc680_auto_init_hp_out(struct hda_codec *codec)
19303{
19304 struct alc_spec *spec = codec->spec;
19305 hda_nid_t pin;
19306
19307 pin = spec->autocfg.hp_pins[0];
19308 if (pin)
19309 alc680_auto_set_output_and_unmute(codec, pin, PIN_HP);
19310 pin = spec->autocfg.speaker_pins[0];
19311 if (pin)
19312 alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT);
19313}
19314
19315/* pcm configuration: identical with ALC880 */
19316#define alc680_pcm_analog_playback alc880_pcm_analog_playback
19317#define alc680_pcm_analog_capture alc880_pcm_analog_capture
19318#define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
19319#define alc680_pcm_digital_playback alc880_pcm_digital_playback
Kailang Yangc69aefa2010-08-17 10:39:22 +020019320#define alc680_pcm_digital_capture alc880_pcm_digital_capture
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019321
19322/*
19323 * BIOS auto configuration
19324 */
19325static int alc680_parse_auto_config(struct hda_codec *codec)
19326{
19327 struct alc_spec *spec = codec->spec;
19328 int err;
19329 static hda_nid_t alc680_ignore[] = { 0 };
19330
19331 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
19332 alc680_ignore);
19333 if (err < 0)
19334 return err;
Kailang Yangc69aefa2010-08-17 10:39:22 +020019335
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019336 if (!spec->autocfg.line_outs) {
19337 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
19338 spec->multiout.max_channels = 2;
19339 spec->no_analog = 1;
19340 goto dig_only;
19341 }
19342 return 0; /* can't find valid BIOS pin config */
19343 }
19344 err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg);
19345 if (err < 0)
19346 return err;
19347
19348 spec->multiout.max_channels = 2;
19349
19350 dig_only:
19351 /* digital only support output */
Takashi Iwai757899a2010-07-30 10:48:14 +020019352 alc_auto_parse_digital(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019353 if (spec->kctls.list)
19354 add_mixer(spec, spec->kctls.list);
19355
19356 add_verb(spec, alc680_init_verbs);
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019357
19358 err = alc_auto_add_mic_boost(codec);
19359 if (err < 0)
19360 return err;
19361
19362 return 1;
19363}
19364
19365#define alc680_auto_init_analog_input alc882_auto_init_analog_input
19366
19367/* init callback for auto-configuration model -- overriding the default init */
19368static void alc680_auto_init(struct hda_codec *codec)
19369{
19370 struct alc_spec *spec = codec->spec;
19371 alc680_auto_init_multi_out(codec);
19372 alc680_auto_init_hp_out(codec);
19373 alc680_auto_init_analog_input(codec);
Takashi Iwai757899a2010-07-30 10:48:14 +020019374 alc_auto_init_digital(codec);
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019375 if (spec->unsol_event)
19376 alc_inithook(codec);
19377}
19378
19379/*
19380 * configuration and preset
19381 */
19382static const char *alc680_models[ALC680_MODEL_LAST] = {
Takashi Iwaid4a86d82010-06-23 17:51:26 +020019383 [ALC680_BASE] = "base",
19384 [ALC680_AUTO] = "auto",
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019385};
19386
19387static struct snd_pci_quirk alc680_cfg_tbl[] = {
19388 SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
19389 {}
19390};
19391
19392static struct alc_config_preset alc680_presets[] = {
19393 [ALC680_BASE] = {
19394 .mixers = { alc680_base_mixer },
Kailang Yangc69aefa2010-08-17 10:39:22 +020019395 .cap_mixer = alc680_master_capture_mixer,
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019396 .init_verbs = { alc680_init_verbs },
19397 .num_dacs = ARRAY_SIZE(alc680_dac_nids),
19398 .dac_nids = alc680_dac_nids,
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019399 .dig_out_nid = ALC680_DIGOUT_NID,
19400 .num_channel_mode = ARRAY_SIZE(alc680_modes),
19401 .channel_mode = alc680_modes,
Kailang Yangc69aefa2010-08-17 10:39:22 +020019402 .unsol_event = alc680_unsol_event,
19403 .setup = alc680_base_setup,
19404 .init_hook = alc680_inithook,
19405
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019406 },
19407};
19408
19409static int patch_alc680(struct hda_codec *codec)
19410{
19411 struct alc_spec *spec;
19412 int board_config;
19413 int err;
19414
19415 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
19416 if (spec == NULL)
19417 return -ENOMEM;
19418
19419 codec->spec = spec;
19420
19421 board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST,
19422 alc680_models,
19423 alc680_cfg_tbl);
19424
19425 if (board_config < 0 || board_config >= ALC680_MODEL_LAST) {
19426 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
19427 codec->chip_name);
19428 board_config = ALC680_AUTO;
19429 }
19430
19431 if (board_config == ALC680_AUTO) {
19432 /* automatic parse from the BIOS config */
19433 err = alc680_parse_auto_config(codec);
19434 if (err < 0) {
19435 alc_free(codec);
19436 return err;
19437 } else if (!err) {
19438 printk(KERN_INFO
19439 "hda_codec: Cannot set up configuration "
19440 "from BIOS. Using base mode...\n");
19441 board_config = ALC680_BASE;
19442 }
19443 }
19444
19445 if (board_config != ALC680_AUTO)
19446 setup_preset(codec, &alc680_presets[board_config]);
19447
19448 spec->stream_analog_playback = &alc680_pcm_analog_playback;
Kailang Yangc69aefa2010-08-17 10:39:22 +020019449 spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019450 spec->stream_digital_playback = &alc680_pcm_digital_playback;
Kailang Yangc69aefa2010-08-17 10:39:22 +020019451 spec->stream_digital_capture = &alc680_pcm_digital_capture;
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019452
19453 if (!spec->adc_nids) {
19454 spec->adc_nids = alc680_adc_nids;
19455 spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids);
19456 }
19457
19458 if (!spec->cap_mixer)
19459 set_capture_mixer(codec);
19460
19461 spec->vmaster_nid = 0x02;
19462
19463 codec->patch_ops = alc_patch_ops;
19464 if (board_config == ALC680_AUTO)
19465 spec->init_hook = alc680_auto_init;
19466
19467 return 0;
19468}
19469
19470/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070019471 * patch entries
19472 */
Takashi Iwai1289e9e2008-11-27 15:47:11 +010019473static struct hda_codec_preset snd_hda_preset_realtek[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070019474 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +010019475 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +010019476 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +020019477 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +010019478 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010019479 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +020019480 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +010019481 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010019482 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +020019483 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010019484 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
19485 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
19486 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020019487 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai49535502009-06-30 15:28:30 +020019488 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +020019489 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
19490 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +020019491 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +010019492 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +010019493 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +020019494 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +010019495 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070019496 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +020019497 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +020019498 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +020019499 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +020019500 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai49535502009-06-30 15:28:30 +020019501 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +010019502 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Takashi Iwai49535502009-06-30 15:28:30 +020019503 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
Kailang Yang44426082008-10-15 11:18:05 +020019504 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai49535502009-06-30 15:28:30 +020019505 .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +010019506 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
Takashi Iwai49535502009-06-30 15:28:30 +020019507 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +010019508 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070019509 {} /* terminator */
19510};
Takashi Iwai1289e9e2008-11-27 15:47:11 +010019511
19512MODULE_ALIAS("snd-hda-codec-id:10ec*");
19513
19514MODULE_LICENSE("GPL");
19515MODULE_DESCRIPTION("Realtek HD-audio codec");
19516
19517static struct hda_codec_preset_list realtek_list = {
19518 .preset = snd_hda_preset_realtek,
19519 .owner = THIS_MODULE,
19520};
19521
19522static int __init patch_realtek_init(void)
19523{
19524 return snd_hda_add_codec_preset(&realtek_list);
19525}
19526
19527static void __exit patch_realtek_exit(void)
19528{
19529 snd_hda_delete_codec_preset(&realtek_list);
19530}
19531
19532module_init(patch_realtek_init)
19533module_exit(patch_realtek_exit)