1 /* 2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984, 3 * AD1986A, AD1988 4 * 5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de> 6 * 7 * This driver is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This driver is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 #include <sound/driver.h> 23 #include <linux/init.h> 24 #include <linux/delay.h> 25 #include <linux/slab.h> 26 #include <linux/pci.h> 27 #include <linux/mutex.h> 28 29 #include <sound/core.h> 30 #include "hda_codec.h" 31 #include "hda_local.h" 32 33 struct ad198x_spec { 34 struct snd_kcontrol_new *mixers[5]; 35 int num_mixers; 36 37 const struct hda_verb *init_verbs[5]; /* initialization verbs 38 * don't forget NULL termination! 39 */ 40 unsigned int num_init_verbs; 41 42 /* playback */ 43 struct hda_multi_out multiout; /* playback set-up 44 * max_channels, dacs must be set 45 * dig_out_nid and hp_nid are optional 46 */ 47 unsigned int cur_eapd; 48 unsigned int need_dac_fix; 49 50 /* capture */ 51 unsigned int num_adc_nids; 52 hda_nid_t *adc_nids; 53 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 54 55 /* capture source */ 56 const struct hda_input_mux *input_mux; 57 hda_nid_t *capsrc_nids; 58 unsigned int cur_mux[3]; 59 60 /* channel model */ 61 const struct hda_channel_mode *channel_mode; 62 int num_channel_mode; 63 64 /* PCM information */ 65 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ 66 67 struct mutex amp_mutex; /* PCM volume/mute control mutex */ 68 unsigned int spdif_route; 69 70 /* dynamic controls, init_verbs and input_mux */ 71 struct auto_pin_cfg autocfg; 72 unsigned int num_kctl_alloc, num_kctl_used; 73 struct snd_kcontrol_new *kctl_alloc; 74 struct hda_input_mux private_imux; 75 hda_nid_t private_dac_nids[4]; 76 77 unsigned int jack_present :1; 78 79 #ifdef CONFIG_SND_HDA_POWER_SAVE 80 struct hda_loopback_check loopback; 81 #endif 82 }; 83 84 /* 85 * input MUX handling (common part) 86 */ 87 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 88 { 89 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 90 struct ad198x_spec *spec = codec->spec; 91 92 return snd_hda_input_mux_info(spec->input_mux, uinfo); 93 } 94 95 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 96 { 97 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 98 struct ad198x_spec *spec = codec->spec; 99 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 100 101 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; 102 return 0; 103 } 104 105 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 106 { 107 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 108 struct ad198x_spec *spec = codec->spec; 109 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 110 111 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, 112 spec->capsrc_nids[adc_idx], 113 &spec->cur_mux[adc_idx]); 114 } 115 116 /* 117 * initialization (common callbacks) 118 */ 119 static int ad198x_init(struct hda_codec *codec) 120 { 121 struct ad198x_spec *spec = codec->spec; 122 int i; 123 124 for (i = 0; i < spec->num_init_verbs; i++) 125 snd_hda_sequence_write(codec, spec->init_verbs[i]); 126 return 0; 127 } 128 129 static int ad198x_build_controls(struct hda_codec *codec) 130 { 131 struct ad198x_spec *spec = codec->spec; 132 unsigned int i; 133 int err; 134 135 for (i = 0; i < spec->num_mixers; i++) { 136 err = snd_hda_add_new_ctls(codec, spec->mixers[i]); 137 if (err < 0) 138 return err; 139 } 140 if (spec->multiout.dig_out_nid) { 141 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); 142 if (err < 0) 143 return err; 144 } 145 if (spec->dig_in_nid) { 146 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 147 if (err < 0) 148 return err; 149 } 150 return 0; 151 } 152 153 #ifdef CONFIG_SND_HDA_POWER_SAVE 154 static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid) 155 { 156 struct ad198x_spec *spec = codec->spec; 157 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); 158 } 159 #endif 160 161 /* 162 * Analog playback callbacks 163 */ 164 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo, 165 struct hda_codec *codec, 166 struct snd_pcm_substream *substream) 167 { 168 struct ad198x_spec *spec = codec->spec; 169 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); 170 } 171 172 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 173 struct hda_codec *codec, 174 unsigned int stream_tag, 175 unsigned int format, 176 struct snd_pcm_substream *substream) 177 { 178 struct ad198x_spec *spec = codec->spec; 179 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, 180 format, substream); 181 } 182 183 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 184 struct hda_codec *codec, 185 struct snd_pcm_substream *substream) 186 { 187 struct ad198x_spec *spec = codec->spec; 188 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); 189 } 190 191 /* 192 * Digital out 193 */ 194 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, 195 struct hda_codec *codec, 196 struct snd_pcm_substream *substream) 197 { 198 struct ad198x_spec *spec = codec->spec; 199 return snd_hda_multi_out_dig_open(codec, &spec->multiout); 200 } 201 202 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, 203 struct hda_codec *codec, 204 struct snd_pcm_substream *substream) 205 { 206 struct ad198x_spec *spec = codec->spec; 207 return snd_hda_multi_out_dig_close(codec, &spec->multiout); 208 } 209 210 static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 211 struct hda_codec *codec, 212 unsigned int stream_tag, 213 unsigned int format, 214 struct snd_pcm_substream *substream) 215 { 216 struct ad198x_spec *spec = codec->spec; 217 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, 218 format, substream); 219 } 220 221 /* 222 * Analog capture 223 */ 224 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 225 struct hda_codec *codec, 226 unsigned int stream_tag, 227 unsigned int format, 228 struct snd_pcm_substream *substream) 229 { 230 struct ad198x_spec *spec = codec->spec; 231 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 232 stream_tag, 0, format); 233 return 0; 234 } 235 236 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, 237 struct hda_codec *codec, 238 struct snd_pcm_substream *substream) 239 { 240 struct ad198x_spec *spec = codec->spec; 241 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 242 0, 0, 0); 243 return 0; 244 } 245 246 247 /* 248 */ 249 static struct hda_pcm_stream ad198x_pcm_analog_playback = { 250 .substreams = 1, 251 .channels_min = 2, 252 .channels_max = 6, /* changed later */ 253 .nid = 0, /* fill later */ 254 .ops = { 255 .open = ad198x_playback_pcm_open, 256 .prepare = ad198x_playback_pcm_prepare, 257 .cleanup = ad198x_playback_pcm_cleanup 258 }, 259 }; 260 261 static struct hda_pcm_stream ad198x_pcm_analog_capture = { 262 .substreams = 1, 263 .channels_min = 2, 264 .channels_max = 2, 265 .nid = 0, /* fill later */ 266 .ops = { 267 .prepare = ad198x_capture_pcm_prepare, 268 .cleanup = ad198x_capture_pcm_cleanup 269 }, 270 }; 271 272 static struct hda_pcm_stream ad198x_pcm_digital_playback = { 273 .substreams = 1, 274 .channels_min = 2, 275 .channels_max = 2, 276 .nid = 0, /* fill later */ 277 .ops = { 278 .open = ad198x_dig_playback_pcm_open, 279 .close = ad198x_dig_playback_pcm_close, 280 .prepare = ad198x_dig_playback_pcm_prepare 281 }, 282 }; 283 284 static struct hda_pcm_stream ad198x_pcm_digital_capture = { 285 .substreams = 1, 286 .channels_min = 2, 287 .channels_max = 2, 288 /* NID is set in alc_build_pcms */ 289 }; 290 291 static int ad198x_build_pcms(struct hda_codec *codec) 292 { 293 struct ad198x_spec *spec = codec->spec; 294 struct hda_pcm *info = spec->pcm_rec; 295 296 codec->num_pcms = 1; 297 codec->pcm_info = info; 298 299 info->name = "AD198x Analog"; 300 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback; 301 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; 302 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; 303 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture; 304 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids; 305 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; 306 307 if (spec->multiout.dig_out_nid) { 308 info++; 309 codec->num_pcms++; 310 info->name = "AD198x Digital"; 311 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; 312 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; 313 if (spec->dig_in_nid) { 314 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture; 315 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; 316 } 317 } 318 319 return 0; 320 } 321 322 static void ad198x_free(struct hda_codec *codec) 323 { 324 struct ad198x_spec *spec = codec->spec; 325 unsigned int i; 326 327 if (spec->kctl_alloc) { 328 for (i = 0; i < spec->num_kctl_used; i++) 329 kfree(spec->kctl_alloc[i].name); 330 kfree(spec->kctl_alloc); 331 } 332 kfree(codec->spec); 333 } 334 335 static struct hda_codec_ops ad198x_patch_ops = { 336 .build_controls = ad198x_build_controls, 337 .build_pcms = ad198x_build_pcms, 338 .init = ad198x_init, 339 .free = ad198x_free, 340 #ifdef CONFIG_SND_HDA_POWER_SAVE 341 .check_power_status = ad198x_check_power_status, 342 #endif 343 }; 344 345 346 /* 347 * EAPD control 348 * the private value = nid | (invert << 8) 349 */ 350 #define ad198x_eapd_info snd_ctl_boolean_mono_info 351 352 static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, 353 struct snd_ctl_elem_value *ucontrol) 354 { 355 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 356 struct ad198x_spec *spec = codec->spec; 357 int invert = (kcontrol->private_value >> 8) & 1; 358 if (invert) 359 ucontrol->value.integer.value[0] = ! spec->cur_eapd; 360 else 361 ucontrol->value.integer.value[0] = spec->cur_eapd; 362 return 0; 363 } 364 365 static int ad198x_eapd_put(struct snd_kcontrol *kcontrol, 366 struct snd_ctl_elem_value *ucontrol) 367 { 368 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 369 struct ad198x_spec *spec = codec->spec; 370 int invert = (kcontrol->private_value >> 8) & 1; 371 hda_nid_t nid = kcontrol->private_value & 0xff; 372 unsigned int eapd; 373 eapd = ucontrol->value.integer.value[0]; 374 if (invert) 375 eapd = !eapd; 376 if (eapd == spec->cur_eapd) 377 return 0; 378 spec->cur_eapd = eapd; 379 snd_hda_codec_write_cache(codec, nid, 380 0, AC_VERB_SET_EAPD_BTLENABLE, 381 eapd ? 0x02 : 0x00); 382 return 1; 383 } 384 385 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, 386 struct snd_ctl_elem_info *uinfo); 387 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, 388 struct snd_ctl_elem_value *ucontrol); 389 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, 390 struct snd_ctl_elem_value *ucontrol); 391 392 393 /* 394 * AD1986A specific 395 */ 396 397 #define AD1986A_SPDIF_OUT 0x02 398 #define AD1986A_FRONT_DAC 0x03 399 #define AD1986A_SURR_DAC 0x04 400 #define AD1986A_CLFE_DAC 0x05 401 #define AD1986A_ADC 0x06 402 403 static hda_nid_t ad1986a_dac_nids[3] = { 404 AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC 405 }; 406 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC }; 407 static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 }; 408 409 static struct hda_input_mux ad1986a_capture_source = { 410 .num_items = 7, 411 .items = { 412 { "Mic", 0x0 }, 413 { "CD", 0x1 }, 414 { "Aux", 0x3 }, 415 { "Line", 0x4 }, 416 { "Mix", 0x5 }, 417 { "Mono", 0x6 }, 418 { "Phone", 0x7 }, 419 }, 420 }; 421 422 423 static struct hda_bind_ctls ad1986a_bind_pcm_vol = { 424 .ops = &snd_hda_bind_vol, 425 .values = { 426 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), 427 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), 428 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), 429 0 430 }, 431 }; 432 433 static struct hda_bind_ctls ad1986a_bind_pcm_sw = { 434 .ops = &snd_hda_bind_sw, 435 .values = { 436 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), 437 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), 438 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), 439 0 440 }, 441 }; 442 443 /* 444 * mixers 445 */ 446 static struct snd_kcontrol_new ad1986a_mixers[] = { 447 /* 448 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity 449 */ 450 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol), 451 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw), 452 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 453 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 454 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 455 HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT), 456 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT), 457 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT), 458 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT), 459 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT), 460 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT), 461 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), 462 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), 463 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), 464 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), 465 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT), 466 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT), 467 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), 468 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 469 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 470 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), 471 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), 472 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), 473 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), 474 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), 475 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), 476 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), 477 { 478 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 479 .name = "Capture Source", 480 .info = ad198x_mux_enum_info, 481 .get = ad198x_mux_enum_get, 482 .put = ad198x_mux_enum_put, 483 }, 484 HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT), 485 { } /* end */ 486 }; 487 488 /* additional mixers for 3stack mode */ 489 static struct snd_kcontrol_new ad1986a_3st_mixers[] = { 490 { 491 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 492 .name = "Channel Mode", 493 .info = ad198x_ch_mode_info, 494 .get = ad198x_ch_mode_get, 495 .put = ad198x_ch_mode_put, 496 }, 497 { } /* end */ 498 }; 499 500 /* laptop model - 2ch only */ 501 static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC }; 502 503 /* master controls both pins 0x1a and 0x1b */ 504 static struct hda_bind_ctls ad1986a_laptop_master_vol = { 505 .ops = &snd_hda_bind_vol, 506 .values = { 507 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), 508 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), 509 0, 510 }, 511 }; 512 513 static struct hda_bind_ctls ad1986a_laptop_master_sw = { 514 .ops = &snd_hda_bind_sw, 515 .values = { 516 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), 517 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), 518 0, 519 }, 520 }; 521 522 static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { 523 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), 524 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), 525 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), 526 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), 527 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), 528 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), 529 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), 530 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT), 531 HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT), 532 HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), 533 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 534 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 535 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), 536 /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), 537 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), 538 HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), 539 HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ 540 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), 541 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), 542 { 543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 544 .name = "Capture Source", 545 .info = ad198x_mux_enum_info, 546 .get = ad198x_mux_enum_get, 547 .put = ad198x_mux_enum_put, 548 }, 549 { } /* end */ 550 }; 551 552 /* laptop-eapd model - 2ch only */ 553 554 static struct hda_input_mux ad1986a_laptop_eapd_capture_source = { 555 .num_items = 3, 556 .items = { 557 { "Mic", 0x0 }, 558 { "Internal Mic", 0x4 }, 559 { "Mix", 0x5 }, 560 }, 561 }; 562 563 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { 564 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), 565 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), 566 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), 567 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), 568 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), 569 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), 570 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 571 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 572 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), 573 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), 574 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), 575 { 576 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 577 .name = "Capture Source", 578 .info = ad198x_mux_enum_info, 579 .get = ad198x_mux_enum_get, 580 .put = ad198x_mux_enum_put, 581 }, 582 { 583 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 584 .name = "External Amplifier", 585 .info = ad198x_eapd_info, 586 .get = ad198x_eapd_get, 587 .put = ad198x_eapd_put, 588 .private_value = 0x1b | (1 << 8), /* port-D, inversed */ 589 }, 590 { } /* end */ 591 }; 592 593 /* laptop-automute - 2ch only */ 594 595 static void ad1986a_update_hp(struct hda_codec *codec) 596 { 597 struct ad198x_spec *spec = codec->spec; 598 unsigned int mute; 599 600 if (spec->jack_present) 601 mute = HDA_AMP_MUTE; /* mute internal speaker */ 602 else 603 /* unmute internal speaker if necessary */ 604 mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0); 605 snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, 606 HDA_AMP_MUTE, mute); 607 } 608 609 static void ad1986a_hp_automute(struct hda_codec *codec) 610 { 611 struct ad198x_spec *spec = codec->spec; 612 unsigned int present; 613 614 present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); 615 spec->jack_present = (present & 0x80000000) != 0; 616 ad1986a_update_hp(codec); 617 } 618 619 #define AD1986A_HP_EVENT 0x37 620 621 static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res) 622 { 623 if ((res >> 26) != AD1986A_HP_EVENT) 624 return; 625 ad1986a_hp_automute(codec); 626 } 627 628 static int ad1986a_hp_init(struct hda_codec *codec) 629 { 630 ad198x_init(codec); 631 ad1986a_hp_automute(codec); 632 return 0; 633 } 634 635 /* bind hp and internal speaker mute (with plug check) */ 636 static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol, 637 struct snd_ctl_elem_value *ucontrol) 638 { 639 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 640 long *valp = ucontrol->value.integer.value; 641 int change; 642 643 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, 644 HDA_AMP_MUTE, 645 valp[0] ? 0 : HDA_AMP_MUTE); 646 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, 647 HDA_AMP_MUTE, 648 valp[1] ? 0 : HDA_AMP_MUTE); 649 if (change) 650 ad1986a_update_hp(codec); 651 return change; 652 } 653 654 static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { 655 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), 656 { 657 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 658 .name = "Master Playback Switch", 659 .info = snd_hda_mixer_amp_switch_info, 660 .get = snd_hda_mixer_amp_switch_get, 661 .put = ad1986a_hp_master_sw_put, 662 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), 663 }, 664 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), 665 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), 666 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), 667 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), 668 HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), 669 HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), 670 HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), 671 HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT), 672 HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT), 673 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), 674 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), 675 { 676 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 677 .name = "Capture Source", 678 .info = ad198x_mux_enum_info, 679 .get = ad198x_mux_enum_get, 680 .put = ad198x_mux_enum_put, 681 }, 682 { 683 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 684 .name = "External Amplifier", 685 .info = ad198x_eapd_info, 686 .get = ad198x_eapd_get, 687 .put = ad198x_eapd_put, 688 .private_value = 0x1b | (1 << 8), /* port-D, inversed */ 689 }, 690 { } /* end */ 691 }; 692 693 /* 694 * initialization verbs 695 */ 696 static struct hda_verb ad1986a_init_verbs[] = { 697 /* Front, Surround, CLFE DAC; mute as default */ 698 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 699 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 700 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 701 /* Downmix - off */ 702 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 703 /* HP, Line-Out, Surround, CLFE selectors */ 704 {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0}, 705 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, 706 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, 707 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 708 /* Mono selector */ 709 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0}, 710 /* Mic selector: Mic 1/2 pin */ 711 {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0}, 712 /* Line-in selector: Line-in */ 713 {0x10, AC_VERB_SET_CONNECT_SEL, 0x0}, 714 /* Mic 1/2 swap */ 715 {0x11, AC_VERB_SET_CONNECT_SEL, 0x0}, 716 /* Record selector: mic */ 717 {0x12, AC_VERB_SET_CONNECT_SEL, 0x0}, 718 /* Mic, Phone, CD, Aux, Line-In amp; mute as default */ 719 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 720 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 721 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 722 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 723 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 724 /* PC beep */ 725 {0x18, AC_VERB_SET_CONNECT_SEL, 0x0}, 726 /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */ 727 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 728 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 729 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 730 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 731 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 732 /* HP Pin */ 733 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 734 /* Front, Surround, CLFE Pins */ 735 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 736 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 737 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 738 /* Mono Pin */ 739 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 740 /* Mic Pin */ 741 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 742 /* Line, Aux, CD, Beep-In Pin */ 743 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 744 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 745 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 746 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 747 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 748 { } /* end */ 749 }; 750 751 static struct hda_verb ad1986a_ch2_init[] = { 752 /* Surround out -> Line In */ 753 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 754 /* Line-in selectors */ 755 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 }, 756 /* CLFE -> Mic in */ 757 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 758 /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */ 759 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, 760 { } /* end */ 761 }; 762 763 static struct hda_verb ad1986a_ch4_init[] = { 764 /* Surround out -> Surround */ 765 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 766 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, 767 /* CLFE -> Mic in */ 768 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 769 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, 770 { } /* end */ 771 }; 772 773 static struct hda_verb ad1986a_ch6_init[] = { 774 /* Surround out -> Surround out */ 775 { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 776 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, 777 /* CLFE -> CLFE */ 778 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 779 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 }, 780 { } /* end */ 781 }; 782 783 static struct hda_channel_mode ad1986a_modes[3] = { 784 { 2, ad1986a_ch2_init }, 785 { 4, ad1986a_ch4_init }, 786 { 6, ad1986a_ch6_init }, 787 }; 788 789 /* eapd initialization */ 790 static struct hda_verb ad1986a_eapd_init_verbs[] = { 791 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, 792 {} 793 }; 794 795 /* Ultra initialization */ 796 static struct hda_verb ad1986a_ultra_init[] = { 797 /* eapd initialization */ 798 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, 799 /* CLFE -> Mic in */ 800 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 }, 801 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 802 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, 803 { } /* end */ 804 }; 805 806 /* pin sensing on HP jack */ 807 static struct hda_verb ad1986a_hp_init_verbs[] = { 808 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT}, 809 {} 810 }; 811 812 813 /* models */ 814 enum { 815 AD1986A_6STACK, 816 AD1986A_3STACK, 817 AD1986A_LAPTOP, 818 AD1986A_LAPTOP_EAPD, 819 AD1986A_LAPTOP_AUTOMUTE, 820 AD1986A_ULTRA, 821 AD1986A_MODELS 822 }; 823 824 static const char *ad1986a_models[AD1986A_MODELS] = { 825 [AD1986A_6STACK] = "6stack", 826 [AD1986A_3STACK] = "3stack", 827 [AD1986A_LAPTOP] = "laptop", 828 [AD1986A_LAPTOP_EAPD] = "laptop-eapd", 829 [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", 830 [AD1986A_ULTRA] = "ultra", 831 }; 832 833 static struct snd_pci_quirk ad1986a_cfg_tbl[] = { 834 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD), 835 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK), 836 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD), 837 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD), 838 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD), 839 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD), 840 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD), 841 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD), 842 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD), 843 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK), 844 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK), 845 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP), 846 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK), 847 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK), 848 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK), 849 SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), 850 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), 851 SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD), 852 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD), 853 SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD), 854 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), 855 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), 856 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), 857 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), 858 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE), 859 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP), 860 {} 861 }; 862 863 #ifdef CONFIG_SND_HDA_POWER_SAVE 864 static struct hda_amp_list ad1986a_loopbacks[] = { 865 { 0x13, HDA_OUTPUT, 0 }, /* Mic */ 866 { 0x14, HDA_OUTPUT, 0 }, /* Phone */ 867 { 0x15, HDA_OUTPUT, 0 }, /* CD */ 868 { 0x16, HDA_OUTPUT, 0 }, /* Aux */ 869 { 0x17, HDA_OUTPUT, 0 }, /* Line */ 870 { } /* end */ 871 }; 872 #endif 873 874 static int patch_ad1986a(struct hda_codec *codec) 875 { 876 struct ad198x_spec *spec; 877 int board_config; 878 879 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 880 if (spec == NULL) 881 return -ENOMEM; 882 883 codec->spec = spec; 884 885 spec->multiout.max_channels = 6; 886 spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); 887 spec->multiout.dac_nids = ad1986a_dac_nids; 888 spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; 889 spec->num_adc_nids = 1; 890 spec->adc_nids = ad1986a_adc_nids; 891 spec->capsrc_nids = ad1986a_capsrc_nids; 892 spec->input_mux = &ad1986a_capture_source; 893 spec->num_mixers = 1; 894 spec->mixers[0] = ad1986a_mixers; 895 spec->num_init_verbs = 1; 896 spec->init_verbs[0] = ad1986a_init_verbs; 897 #ifdef CONFIG_SND_HDA_POWER_SAVE 898 spec->loopback.amplist = ad1986a_loopbacks; 899 #endif 900 901 codec->patch_ops = ad198x_patch_ops; 902 903 /* override some parameters */ 904 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS, 905 ad1986a_models, 906 ad1986a_cfg_tbl); 907 switch (board_config) { 908 case AD1986A_3STACK: 909 spec->num_mixers = 2; 910 spec->mixers[1] = ad1986a_3st_mixers; 911 spec->num_init_verbs = 2; 912 spec->init_verbs[1] = ad1986a_ch2_init; 913 spec->channel_mode = ad1986a_modes; 914 spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); 915 spec->need_dac_fix = 1; 916 spec->multiout.max_channels = 2; 917 spec->multiout.num_dacs = 1; 918 break; 919 case AD1986A_LAPTOP: 920 spec->mixers[0] = ad1986a_laptop_mixers; 921 spec->multiout.max_channels = 2; 922 spec->multiout.num_dacs = 1; 923 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 924 break; 925 case AD1986A_LAPTOP_EAPD: 926 spec->mixers[0] = ad1986a_laptop_eapd_mixers; 927 spec->num_init_verbs = 2; 928 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 929 spec->multiout.max_channels = 2; 930 spec->multiout.num_dacs = 1; 931 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 932 spec->multiout.dig_out_nid = 0; 933 spec->input_mux = &ad1986a_laptop_eapd_capture_source; 934 break; 935 case AD1986A_LAPTOP_AUTOMUTE: 936 spec->mixers[0] = ad1986a_laptop_automute_mixers; 937 spec->num_init_verbs = 3; 938 spec->init_verbs[1] = ad1986a_eapd_init_verbs; 939 spec->init_verbs[2] = ad1986a_hp_init_verbs; 940 spec->multiout.max_channels = 2; 941 spec->multiout.num_dacs = 1; 942 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 943 spec->multiout.dig_out_nid = 0; 944 spec->input_mux = &ad1986a_laptop_eapd_capture_source; 945 codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; 946 codec->patch_ops.init = ad1986a_hp_init; 947 break; 948 case AD1986A_ULTRA: 949 spec->mixers[0] = ad1986a_laptop_eapd_mixers; 950 spec->num_init_verbs = 2; 951 spec->init_verbs[1] = ad1986a_ultra_init; 952 spec->multiout.max_channels = 2; 953 spec->multiout.num_dacs = 1; 954 spec->multiout.dac_nids = ad1986a_laptop_dac_nids; 955 spec->multiout.dig_out_nid = 0; 956 break; 957 } 958 959 return 0; 960 } 961 962 /* 963 * AD1983 specific 964 */ 965 966 #define AD1983_SPDIF_OUT 0x02 967 #define AD1983_DAC 0x03 968 #define AD1983_ADC 0x04 969 970 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; 971 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC }; 972 static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 }; 973 974 static struct hda_input_mux ad1983_capture_source = { 975 .num_items = 4, 976 .items = { 977 { "Mic", 0x0 }, 978 { "Line", 0x1 }, 979 { "Mix", 0x2 }, 980 { "Mix Mono", 0x3 }, 981 }, 982 }; 983 984 /* 985 * SPDIF playback route 986 */ 987 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 988 { 989 static char *texts[] = { "PCM", "ADC" }; 990 991 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 992 uinfo->count = 1; 993 uinfo->value.enumerated.items = 2; 994 if (uinfo->value.enumerated.item > 1) 995 uinfo->value.enumerated.item = 1; 996 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 997 return 0; 998 } 999 1000 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1001 { 1002 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1003 struct ad198x_spec *spec = codec->spec; 1004 1005 ucontrol->value.enumerated.item[0] = spec->spdif_route; 1006 return 0; 1007 } 1008 1009 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1010 { 1011 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1012 struct ad198x_spec *spec = codec->spec; 1013 1014 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { 1015 spec->spdif_route = ucontrol->value.enumerated.item[0]; 1016 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0, 1017 AC_VERB_SET_CONNECT_SEL, 1018 spec->spdif_route); 1019 return 1; 1020 } 1021 return 0; 1022 } 1023 1024 static struct snd_kcontrol_new ad1983_mixers[] = { 1025 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1026 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), 1027 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), 1028 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), 1029 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), 1030 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), 1031 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1032 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1033 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1034 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1035 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1036 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1037 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT), 1038 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT), 1039 HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), 1040 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1041 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1042 { 1043 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1044 .name = "Capture Source", 1045 .info = ad198x_mux_enum_info, 1046 .get = ad198x_mux_enum_get, 1047 .put = ad198x_mux_enum_put, 1048 }, 1049 { 1050 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1051 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 1052 .info = ad1983_spdif_route_info, 1053 .get = ad1983_spdif_route_get, 1054 .put = ad1983_spdif_route_put, 1055 }, 1056 { } /* end */ 1057 }; 1058 1059 static struct hda_verb ad1983_init_verbs[] = { 1060 /* Front, HP, Mono; mute as default */ 1061 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1062 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1063 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1064 /* Beep, PCM, Mic, Line-In: mute */ 1065 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1066 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1067 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1068 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1069 /* Front, HP selectors; from Mix */ 1070 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, 1071 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, 1072 /* Mono selector; from Mix */ 1073 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, 1074 /* Mic selector; Mic */ 1075 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, 1076 /* Line-in selector: Line-in */ 1077 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, 1078 /* Mic boost: 0dB */ 1079 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1080 /* Record selector: mic */ 1081 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, 1082 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1083 /* SPDIF route: PCM */ 1084 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, 1085 /* Front Pin */ 1086 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1087 /* HP Pin */ 1088 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 1089 /* Mono Pin */ 1090 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1091 /* Mic Pin */ 1092 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1093 /* Line Pin */ 1094 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1095 { } /* end */ 1096 }; 1097 1098 #ifdef CONFIG_SND_HDA_POWER_SAVE 1099 static struct hda_amp_list ad1983_loopbacks[] = { 1100 { 0x12, HDA_OUTPUT, 0 }, /* Mic */ 1101 { 0x13, HDA_OUTPUT, 0 }, /* Line */ 1102 { } /* end */ 1103 }; 1104 #endif 1105 1106 static int patch_ad1983(struct hda_codec *codec) 1107 { 1108 struct ad198x_spec *spec; 1109 1110 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1111 if (spec == NULL) 1112 return -ENOMEM; 1113 1114 codec->spec = spec; 1115 1116 spec->multiout.max_channels = 2; 1117 spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); 1118 spec->multiout.dac_nids = ad1983_dac_nids; 1119 spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; 1120 spec->num_adc_nids = 1; 1121 spec->adc_nids = ad1983_adc_nids; 1122 spec->capsrc_nids = ad1983_capsrc_nids; 1123 spec->input_mux = &ad1983_capture_source; 1124 spec->num_mixers = 1; 1125 spec->mixers[0] = ad1983_mixers; 1126 spec->num_init_verbs = 1; 1127 spec->init_verbs[0] = ad1983_init_verbs; 1128 spec->spdif_route = 0; 1129 #ifdef CONFIG_SND_HDA_POWER_SAVE 1130 spec->loopback.amplist = ad1983_loopbacks; 1131 #endif 1132 1133 codec->patch_ops = ad198x_patch_ops; 1134 1135 return 0; 1136 } 1137 1138 1139 /* 1140 * AD1981 HD specific 1141 */ 1142 1143 #define AD1981_SPDIF_OUT 0x02 1144 #define AD1981_DAC 0x03 1145 #define AD1981_ADC 0x04 1146 1147 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; 1148 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC }; 1149 static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 }; 1150 1151 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ 1152 static struct hda_input_mux ad1981_capture_source = { 1153 .num_items = 7, 1154 .items = { 1155 { "Front Mic", 0x0 }, 1156 { "Line", 0x1 }, 1157 { "Mix", 0x2 }, 1158 { "Mix Mono", 0x3 }, 1159 { "CD", 0x4 }, 1160 { "Mic", 0x6 }, 1161 { "Aux", 0x7 }, 1162 }, 1163 }; 1164 1165 static struct snd_kcontrol_new ad1981_mixers[] = { 1166 HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1167 HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), 1168 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), 1169 HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), 1170 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), 1171 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), 1172 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1173 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1174 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1175 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1176 HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1177 HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1178 HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 1179 HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 1180 HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 1181 HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), 1182 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1183 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1184 HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), 1185 HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT), 1186 HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), 1187 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), 1188 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1189 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1190 { 1191 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1192 .name = "Capture Source", 1193 .info = ad198x_mux_enum_info, 1194 .get = ad198x_mux_enum_get, 1195 .put = ad198x_mux_enum_put, 1196 }, 1197 /* identical with AD1983 */ 1198 { 1199 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1200 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 1201 .info = ad1983_spdif_route_info, 1202 .get = ad1983_spdif_route_get, 1203 .put = ad1983_spdif_route_put, 1204 }, 1205 { } /* end */ 1206 }; 1207 1208 static struct hda_verb ad1981_init_verbs[] = { 1209 /* Front, HP, Mono; mute as default */ 1210 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1211 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1212 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1213 /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */ 1214 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1215 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1216 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1217 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1218 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1219 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1220 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1221 /* Front, HP selectors; from Mix */ 1222 {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, 1223 {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, 1224 /* Mono selector; from Mix */ 1225 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, 1226 /* Mic Mixer; select Front Mic */ 1227 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1228 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1229 /* Mic boost: 0dB */ 1230 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1231 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1232 /* Record selector: Front mic */ 1233 {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, 1234 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1235 /* SPDIF route: PCM */ 1236 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, 1237 /* Front Pin */ 1238 {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1239 /* HP Pin */ 1240 {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 1241 /* Mono Pin */ 1242 {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 1243 /* Front & Rear Mic Pins */ 1244 {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1245 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 1246 /* Line Pin */ 1247 {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 1248 /* Digital Beep */ 1249 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, 1250 /* Line-Out as Input: disabled */ 1251 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1252 { } /* end */ 1253 }; 1254 1255 #ifdef CONFIG_SND_HDA_POWER_SAVE 1256 static struct hda_amp_list ad1981_loopbacks[] = { 1257 { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ 1258 { 0x13, HDA_OUTPUT, 0 }, /* Line */ 1259 { 0x1b, HDA_OUTPUT, 0 }, /* Aux */ 1260 { 0x1c, HDA_OUTPUT, 0 }, /* Mic */ 1261 { 0x1d, HDA_OUTPUT, 0 }, /* CD */ 1262 { } /* end */ 1263 }; 1264 #endif 1265 1266 /* 1267 * Patch for HP nx6320 1268 * 1269 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal 1270 * speaker output enabled _and_ mute-LED off. 1271 */ 1272 1273 #define AD1981_HP_EVENT 0x37 1274 #define AD1981_MIC_EVENT 0x38 1275 1276 static struct hda_verb ad1981_hp_init_verbs[] = { 1277 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */ 1278 /* pin sensing on HP and Mic jacks */ 1279 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, 1280 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, 1281 {} 1282 }; 1283 1284 /* turn on/off EAPD (+ mute HP) as a master switch */ 1285 static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol, 1286 struct snd_ctl_elem_value *ucontrol) 1287 { 1288 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1289 struct ad198x_spec *spec = codec->spec; 1290 1291 if (! ad198x_eapd_put(kcontrol, ucontrol)) 1292 return 0; 1293 1294 /* toggle HP mute appropriately */ 1295 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0, 1296 HDA_AMP_MUTE, 1297 spec->cur_eapd ? 0 : HDA_AMP_MUTE); 1298 return 1; 1299 } 1300 1301 /* bind volumes of both NID 0x05 and 0x06 */ 1302 static struct hda_bind_ctls ad1981_hp_bind_master_vol = { 1303 .ops = &snd_hda_bind_vol, 1304 .values = { 1305 HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), 1306 HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT), 1307 0 1308 }, 1309 }; 1310 1311 /* mute internal speaker if HP is plugged */ 1312 static void ad1981_hp_automute(struct hda_codec *codec) 1313 { 1314 unsigned int present; 1315 1316 present = snd_hda_codec_read(codec, 0x06, 0, 1317 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1318 snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, 1319 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); 1320 } 1321 1322 /* toggle input of built-in and mic jack appropriately */ 1323 static void ad1981_hp_automic(struct hda_codec *codec) 1324 { 1325 static struct hda_verb mic_jack_on[] = { 1326 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1327 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1328 {} 1329 }; 1330 static struct hda_verb mic_jack_off[] = { 1331 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 1332 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 1333 {} 1334 }; 1335 unsigned int present; 1336 1337 present = snd_hda_codec_read(codec, 0x08, 0, 1338 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 1339 if (present) 1340 snd_hda_sequence_write(codec, mic_jack_on); 1341 else 1342 snd_hda_sequence_write(codec, mic_jack_off); 1343 } 1344 1345 /* unsolicited event for HP jack sensing */ 1346 static void ad1981_hp_unsol_event(struct hda_codec *codec, 1347 unsigned int res) 1348 { 1349 res >>= 26; 1350 switch (res) { 1351 case AD1981_HP_EVENT: 1352 ad1981_hp_automute(codec); 1353 break; 1354 case AD1981_MIC_EVENT: 1355 ad1981_hp_automic(codec); 1356 break; 1357 } 1358 } 1359 1360 static struct hda_input_mux ad1981_hp_capture_source = { 1361 .num_items = 3, 1362 .items = { 1363 { "Mic", 0x0 }, 1364 { "Docking-Station", 0x1 }, 1365 { "Mix", 0x2 }, 1366 }, 1367 }; 1368 1369 static struct snd_kcontrol_new ad1981_hp_mixers[] = { 1370 HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), 1371 { 1372 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1373 .name = "Master Playback Switch", 1374 .info = ad198x_eapd_info, 1375 .get = ad198x_eapd_get, 1376 .put = ad1981_hp_master_sw_put, 1377 .private_value = 0x05, 1378 }, 1379 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1380 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1381 #if 0 1382 /* FIXME: analog mic/line loopback doesn't work with my tests... 1383 * (although recording is OK) 1384 */ 1385 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1386 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1387 HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1388 HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1389 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 1390 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), 1391 /* FIXME: does this laptop have analog CD connection? */ 1392 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1393 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1394 #endif 1395 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT), 1396 HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT), 1397 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1398 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1399 { 1400 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1401 .name = "Capture Source", 1402 .info = ad198x_mux_enum_info, 1403 .get = ad198x_mux_enum_get, 1404 .put = ad198x_mux_enum_put, 1405 }, 1406 { } /* end */ 1407 }; 1408 1409 /* initialize jack-sensing, too */ 1410 static int ad1981_hp_init(struct hda_codec *codec) 1411 { 1412 ad198x_init(codec); 1413 ad1981_hp_automute(codec); 1414 ad1981_hp_automic(codec); 1415 return 0; 1416 } 1417 1418 /* configuration for Toshiba Laptops */ 1419 static struct hda_verb ad1981_toshiba_init_verbs[] = { 1420 {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */ 1421 /* pin sensing on HP and Mic jacks */ 1422 {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, 1423 {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, 1424 {} 1425 }; 1426 1427 static struct snd_kcontrol_new ad1981_toshiba_mixers[] = { 1428 HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT), 1429 HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT), 1430 { } 1431 }; 1432 1433 /* configuration for Lenovo Thinkpad T60 */ 1434 static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = { 1435 HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1436 HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT), 1437 HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), 1438 HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), 1439 HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), 1440 HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), 1441 HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1442 HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1443 HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT), 1444 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 1445 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), 1446 { 1447 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1448 .name = "Capture Source", 1449 .info = ad198x_mux_enum_info, 1450 .get = ad198x_mux_enum_get, 1451 .put = ad198x_mux_enum_put, 1452 }, 1453 /* identical with AD1983 */ 1454 { 1455 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1456 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 1457 .info = ad1983_spdif_route_info, 1458 .get = ad1983_spdif_route_get, 1459 .put = ad1983_spdif_route_put, 1460 }, 1461 { } /* end */ 1462 }; 1463 1464 static struct hda_input_mux ad1981_thinkpad_capture_source = { 1465 .num_items = 3, 1466 .items = { 1467 { "Mic", 0x0 }, 1468 { "Mix", 0x2 }, 1469 { "CD", 0x4 }, 1470 }, 1471 }; 1472 1473 /* models */ 1474 enum { 1475 AD1981_BASIC, 1476 AD1981_HP, 1477 AD1981_THINKPAD, 1478 AD1981_TOSHIBA, 1479 AD1981_MODELS 1480 }; 1481 1482 static const char *ad1981_models[AD1981_MODELS] = { 1483 [AD1981_HP] = "hp", 1484 [AD1981_THINKPAD] = "thinkpad", 1485 [AD1981_BASIC] = "basic", 1486 [AD1981_TOSHIBA] = "toshiba" 1487 }; 1488 1489 static struct snd_pci_quirk ad1981_cfg_tbl[] = { 1490 /* All HP models */ 1491 SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP), 1492 /* HP nx6320 (reversed SSID, H/W bug) */ 1493 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), 1494 /* Lenovo Thinkpad T60/X60/Z6xx */ 1495 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD), 1496 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), 1497 SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), 1498 {} 1499 }; 1500 1501 static int patch_ad1981(struct hda_codec *codec) 1502 { 1503 struct ad198x_spec *spec; 1504 int board_config; 1505 1506 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1507 if (spec == NULL) 1508 return -ENOMEM; 1509 1510 codec->spec = spec; 1511 1512 spec->multiout.max_channels = 2; 1513 spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); 1514 spec->multiout.dac_nids = ad1981_dac_nids; 1515 spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; 1516 spec->num_adc_nids = 1; 1517 spec->adc_nids = ad1981_adc_nids; 1518 spec->capsrc_nids = ad1981_capsrc_nids; 1519 spec->input_mux = &ad1981_capture_source; 1520 spec->num_mixers = 1; 1521 spec->mixers[0] = ad1981_mixers; 1522 spec->num_init_verbs = 1; 1523 spec->init_verbs[0] = ad1981_init_verbs; 1524 spec->spdif_route = 0; 1525 #ifdef CONFIG_SND_HDA_POWER_SAVE 1526 spec->loopback.amplist = ad1981_loopbacks; 1527 #endif 1528 1529 codec->patch_ops = ad198x_patch_ops; 1530 1531 /* override some parameters */ 1532 board_config = snd_hda_check_board_config(codec, AD1981_MODELS, 1533 ad1981_models, 1534 ad1981_cfg_tbl); 1535 switch (board_config) { 1536 case AD1981_HP: 1537 spec->mixers[0] = ad1981_hp_mixers; 1538 spec->num_init_verbs = 2; 1539 spec->init_verbs[1] = ad1981_hp_init_verbs; 1540 spec->multiout.dig_out_nid = 0; 1541 spec->input_mux = &ad1981_hp_capture_source; 1542 1543 codec->patch_ops.init = ad1981_hp_init; 1544 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 1545 break; 1546 case AD1981_THINKPAD: 1547 spec->mixers[0] = ad1981_thinkpad_mixers; 1548 spec->input_mux = &ad1981_thinkpad_capture_source; 1549 break; 1550 case AD1981_TOSHIBA: 1551 spec->mixers[0] = ad1981_hp_mixers; 1552 spec->mixers[1] = ad1981_toshiba_mixers; 1553 spec->num_init_verbs = 2; 1554 spec->init_verbs[1] = ad1981_toshiba_init_verbs; 1555 spec->multiout.dig_out_nid = 0; 1556 spec->input_mux = &ad1981_hp_capture_source; 1557 codec->patch_ops.init = ad1981_hp_init; 1558 codec->patch_ops.unsol_event = ad1981_hp_unsol_event; 1559 break; 1560 } 1561 return 0; 1562 } 1563 1564 1565 /* 1566 * AD1988 1567 * 1568 * Output pins and routes 1569 * 1570 * Pin Mix Sel DAC (*) 1571 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06 1572 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06 1573 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a 1574 * port-D 0x12 (mute/hp) <- 0x29 <- 04 1575 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a 1576 * port-F 0x16 (mute) <- 0x2a <- 06 1577 * port-G 0x24 (mute) <- 0x27 <- 05 1578 * port-H 0x25 (mute) <- 0x28 <- 0a 1579 * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06 1580 * 1581 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah 1582 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug. 1583 * 1584 * Input pins and routes 1585 * 1586 * pin boost mix input # / adc input # 1587 * port-A 0x11 -> 0x38 -> mix 2, ADC 0 1588 * port-B 0x14 -> 0x39 -> mix 0, ADC 1 1589 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2 1590 * port-D 0x12 -> 0x3d -> mix 3, ADC 8 1591 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4 1592 * port-F 0x16 -> 0x3b -> mix 5, ADC 3 1593 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6 1594 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7 1595 * 1596 * 1597 * DAC assignment 1598 * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03 1599 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03 1600 * 1601 * Inputs of Analog Mix (0x20) 1602 * 0:Port-B (front mic) 1603 * 1:Port-C/G/H (line-in) 1604 * 2:Port-A 1605 * 3:Port-D (line-in/2) 1606 * 4:Port-E/G/H (mic-in) 1607 * 5:Port-F (mic2-in) 1608 * 6:CD 1609 * 7:Beep 1610 * 1611 * ADC selection 1612 * 0:Port-A 1613 * 1:Port-B (front mic-in) 1614 * 2:Port-C (line-in) 1615 * 3:Port-F (mic2-in) 1616 * 4:Port-E (mic-in) 1617 * 5:CD 1618 * 6:Port-G 1619 * 7:Port-H 1620 * 8:Port-D (line-in/2) 1621 * 9:Mix 1622 * 1623 * Proposed pin assignments by the datasheet 1624 * 1625 * 6-stack 1626 * Port-A front headphone 1627 * B front mic-in 1628 * C rear line-in 1629 * D rear front-out 1630 * E rear mic-in 1631 * F rear surround 1632 * G rear CLFE 1633 * H rear side 1634 * 1635 * 3-stack 1636 * Port-A front headphone 1637 * B front mic 1638 * C rear line-in/surround 1639 * D rear front-out 1640 * E rear mic-in/CLFE 1641 * 1642 * laptop 1643 * Port-A headphone 1644 * B mic-in 1645 * C docking station 1646 * D internal speaker (with EAPD) 1647 * E/F quad mic array 1648 */ 1649 1650 1651 /* models */ 1652 enum { 1653 AD1988_6STACK, 1654 AD1988_6STACK_DIG, 1655 AD1988_3STACK, 1656 AD1988_3STACK_DIG, 1657 AD1988_LAPTOP, 1658 AD1988_LAPTOP_DIG, 1659 AD1988_AUTO, 1660 AD1988_MODEL_LAST, 1661 }; 1662 1663 /* reivision id to check workarounds */ 1664 #define AD1988A_REV2 0x100200 1665 1666 #define is_rev2(codec) \ 1667 ((codec)->vendor_id == 0x11d41988 && \ 1668 (codec)->revision_id == AD1988A_REV2) 1669 1670 /* 1671 * mixers 1672 */ 1673 1674 static hda_nid_t ad1988_6stack_dac_nids[4] = { 1675 0x04, 0x06, 0x05, 0x0a 1676 }; 1677 1678 static hda_nid_t ad1988_3stack_dac_nids[3] = { 1679 0x04, 0x05, 0x0a 1680 }; 1681 1682 /* for AD1988A revision-2, DAC2-4 are swapped */ 1683 static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = { 1684 0x04, 0x05, 0x0a, 0x06 1685 }; 1686 1687 static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = { 1688 0x04, 0x0a, 0x06 1689 }; 1690 1691 static hda_nid_t ad1988_adc_nids[3] = { 1692 0x08, 0x09, 0x0f 1693 }; 1694 1695 static hda_nid_t ad1988_capsrc_nids[3] = { 1696 0x0c, 0x0d, 0x0e 1697 }; 1698 1699 #define AD1988_SPDIF_OUT 0x02 1700 #define AD1988_SPDIF_IN 0x07 1701 1702 static struct hda_input_mux ad1988_6stack_capture_source = { 1703 .num_items = 5, 1704 .items = { 1705 { "Front Mic", 0x0 }, 1706 { "Line", 0x1 }, 1707 { "Mic", 0x4 }, 1708 { "CD", 0x5 }, 1709 { "Mix", 0x9 }, 1710 }, 1711 }; 1712 1713 static struct hda_input_mux ad1988_laptop_capture_source = { 1714 .num_items = 3, 1715 .items = { 1716 { "Mic/Line", 0x0 }, 1717 { "CD", 0x5 }, 1718 { "Mix", 0x9 }, 1719 }, 1720 }; 1721 1722 /* 1723 */ 1724 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, 1725 struct snd_ctl_elem_info *uinfo) 1726 { 1727 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1728 struct ad198x_spec *spec = codec->spec; 1729 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, 1730 spec->num_channel_mode); 1731 } 1732 1733 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, 1734 struct snd_ctl_elem_value *ucontrol) 1735 { 1736 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1737 struct ad198x_spec *spec = codec->spec; 1738 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, 1739 spec->num_channel_mode, spec->multiout.max_channels); 1740 } 1741 1742 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, 1743 struct snd_ctl_elem_value *ucontrol) 1744 { 1745 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1746 struct ad198x_spec *spec = codec->spec; 1747 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, 1748 spec->num_channel_mode, 1749 &spec->multiout.max_channels); 1750 if (err >= 0 && spec->need_dac_fix) 1751 spec->multiout.num_dacs = spec->multiout.max_channels / 2; 1752 return err; 1753 } 1754 1755 /* 6-stack mode */ 1756 static struct snd_kcontrol_new ad1988_6stack_mixers1[] = { 1757 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 1758 HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT), 1759 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 1760 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 1761 HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 1762 { } /* end */ 1763 }; 1764 1765 static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = { 1766 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 1767 HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT), 1768 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 1769 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT), 1770 HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT), 1771 { } /* end */ 1772 }; 1773 1774 static struct snd_kcontrol_new ad1988_6stack_mixers2[] = { 1775 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), 1776 HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT), 1777 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT), 1778 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT), 1779 HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT), 1780 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), 1781 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 1782 1783 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 1784 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 1785 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 1786 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 1787 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 1788 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 1789 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), 1790 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), 1791 1792 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), 1793 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), 1794 1795 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 1796 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 1797 1798 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT), 1799 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT), 1800 1801 { } /* end */ 1802 }; 1803 1804 /* 3-stack mode */ 1805 static struct snd_kcontrol_new ad1988_3stack_mixers1[] = { 1806 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 1807 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 1808 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 1809 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 1810 { } /* end */ 1811 }; 1812 1813 static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = { 1814 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 1815 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), 1816 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT), 1817 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT), 1818 { } /* end */ 1819 }; 1820 1821 static struct snd_kcontrol_new ad1988_3stack_mixers2[] = { 1822 HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), 1823 HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT), 1824 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT), 1825 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT), 1826 HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), 1827 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 1828 1829 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 1830 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 1831 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 1832 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 1833 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 1834 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 1835 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), 1836 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), 1837 1838 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), 1839 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), 1840 1841 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 1842 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 1843 1844 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT), 1845 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT), 1846 { 1847 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1848 .name = "Channel Mode", 1849 .info = ad198x_ch_mode_info, 1850 .get = ad198x_ch_mode_get, 1851 .put = ad198x_ch_mode_put, 1852 }, 1853 1854 { } /* end */ 1855 }; 1856 1857 /* laptop mode */ 1858 static struct snd_kcontrol_new ad1988_laptop_mixers[] = { 1859 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 1860 HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT), 1861 HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), 1862 1863 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), 1864 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), 1865 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT), 1866 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT), 1867 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), 1868 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), 1869 1870 HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), 1871 HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), 1872 1873 HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), 1874 HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), 1875 1876 HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT), 1877 1878 { 1879 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1880 .name = "External Amplifier", 1881 .info = ad198x_eapd_info, 1882 .get = ad198x_eapd_get, 1883 .put = ad198x_eapd_put, 1884 .private_value = 0x12 | (1 << 8), /* port-D, inversed */ 1885 }, 1886 1887 { } /* end */ 1888 }; 1889 1890 /* capture */ 1891 static struct snd_kcontrol_new ad1988_capture_mixers[] = { 1892 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 1893 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 1894 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 1895 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 1896 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT), 1897 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT), 1898 { 1899 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1900 /* The multiple "Capture Source" controls confuse alsamixer 1901 * So call somewhat different.. 1902 * FIXME: the controls appear in the "playback" view! 1903 */ 1904 /* .name = "Capture Source", */ 1905 .name = "Input Source", 1906 .count = 3, 1907 .info = ad198x_mux_enum_info, 1908 .get = ad198x_mux_enum_get, 1909 .put = ad198x_mux_enum_put, 1910 }, 1911 { } /* end */ 1912 }; 1913 1914 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol, 1915 struct snd_ctl_elem_info *uinfo) 1916 { 1917 static char *texts[] = { 1918 "PCM", "ADC1", "ADC2", "ADC3" 1919 }; 1920 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1921 uinfo->count = 1; 1922 uinfo->value.enumerated.items = 4; 1923 if (uinfo->value.enumerated.item >= 4) 1924 uinfo->value.enumerated.item = 3; 1925 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1926 return 0; 1927 } 1928 1929 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, 1930 struct snd_ctl_elem_value *ucontrol) 1931 { 1932 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1933 unsigned int sel; 1934 1935 sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE, 1936 AC_AMP_GET_INPUT); 1937 if (!(sel & 0x80)) 1938 ucontrol->value.enumerated.item[0] = 0; 1939 else { 1940 sel = snd_hda_codec_read(codec, 0x0b, 0, 1941 AC_VERB_GET_CONNECT_SEL, 0); 1942 if (sel < 3) 1943 sel++; 1944 else 1945 sel = 0; 1946 ucontrol->value.enumerated.item[0] = sel; 1947 } 1948 return 0; 1949 } 1950 1951 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, 1952 struct snd_ctl_elem_value *ucontrol) 1953 { 1954 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1955 unsigned int val, sel; 1956 int change; 1957 1958 val = ucontrol->value.enumerated.item[0]; 1959 if (!val) { 1960 sel = snd_hda_codec_read(codec, 0x1d, 0, 1961 AC_VERB_GET_AMP_GAIN_MUTE, 1962 AC_AMP_GET_INPUT); 1963 change = sel & 0x80; 1964 if (change) { 1965 snd_hda_codec_write_cache(codec, 0x1d, 0, 1966 AC_VERB_SET_AMP_GAIN_MUTE, 1967 AMP_IN_UNMUTE(0)); 1968 snd_hda_codec_write_cache(codec, 0x1d, 0, 1969 AC_VERB_SET_AMP_GAIN_MUTE, 1970 AMP_IN_MUTE(1)); 1971 } 1972 } else { 1973 sel = snd_hda_codec_read(codec, 0x1d, 0, 1974 AC_VERB_GET_AMP_GAIN_MUTE, 1975 AC_AMP_GET_INPUT | 0x01); 1976 change = sel & 0x80; 1977 if (change) { 1978 snd_hda_codec_write_cache(codec, 0x1d, 0, 1979 AC_VERB_SET_AMP_GAIN_MUTE, 1980 AMP_IN_MUTE(0)); 1981 snd_hda_codec_write_cache(codec, 0x1d, 0, 1982 AC_VERB_SET_AMP_GAIN_MUTE, 1983 AMP_IN_UNMUTE(1)); 1984 } 1985 sel = snd_hda_codec_read(codec, 0x0b, 0, 1986 AC_VERB_GET_CONNECT_SEL, 0) + 1; 1987 change |= sel != val; 1988 if (change) 1989 snd_hda_codec_write_cache(codec, 0x0b, 0, 1990 AC_VERB_SET_CONNECT_SEL, 1991 val - 1); 1992 } 1993 return change; 1994 } 1995 1996 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = { 1997 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 1998 { 1999 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2000 .name = "IEC958 Playback Source", 2001 .info = ad1988_spdif_playback_source_info, 2002 .get = ad1988_spdif_playback_source_get, 2003 .put = ad1988_spdif_playback_source_put, 2004 }, 2005 { } /* end */ 2006 }; 2007 2008 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = { 2009 HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT), 2010 { } /* end */ 2011 }; 2012 2013 2014 /* 2015 * initialization verbs 2016 */ 2017 2018 /* 2019 * for 6-stack (+dig) 2020 */ 2021 static struct hda_verb ad1988_6stack_init_verbs[] = { 2022 /* Front, Surround, CLFE, side DAC; unmute as default */ 2023 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2024 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2025 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2026 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2027 /* Port-A front headphon path */ 2028 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */ 2029 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2030 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2031 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2032 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2033 /* Port-D line-out path */ 2034 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2035 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2036 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2037 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2038 /* Port-F surround path */ 2039 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2040 {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2041 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2042 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2043 /* Port-G CLFE path */ 2044 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2045 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2046 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2047 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2048 /* Port-H side path */ 2049 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2050 {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2051 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2052 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2053 /* Mono out path */ 2054 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2055 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2056 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2057 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2058 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2059 /* Port-B front mic-in path */ 2060 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2061 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2062 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2063 /* Port-C line-in path */ 2064 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2065 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2066 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2067 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2068 /* Port-E mic-in path */ 2069 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2070 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2071 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2072 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, 2073 2074 { } 2075 }; 2076 2077 static struct hda_verb ad1988_capture_init_verbs[] = { 2078 /* mute analog mix */ 2079 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2080 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2081 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2082 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2083 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2084 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2085 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2086 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2087 /* select ADCs - front-mic */ 2088 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2089 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2090 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2091 /* ADCs; muted */ 2092 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2093 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2094 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2095 2096 { } 2097 }; 2098 2099 static struct hda_verb ad1988_spdif_init_verbs[] = { 2100 /* SPDIF out sel */ 2101 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 2102 {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ 2103 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2104 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2105 /* SPDIF out pin */ 2106 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2107 2108 { } 2109 }; 2110 2111 /* 2112 * verbs for 3stack (+dig) 2113 */ 2114 static struct hda_verb ad1988_3stack_ch2_init[] = { 2115 /* set port-C to line-in */ 2116 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2117 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 2118 /* set port-E to mic-in */ 2119 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2120 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, 2121 { } /* end */ 2122 }; 2123 2124 static struct hda_verb ad1988_3stack_ch6_init[] = { 2125 /* set port-C to surround out */ 2126 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2127 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2128 /* set port-E to CLFE out */ 2129 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, 2130 { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2131 { } /* end */ 2132 }; 2133 2134 static struct hda_channel_mode ad1988_3stack_modes[2] = { 2135 { 2, ad1988_3stack_ch2_init }, 2136 { 6, ad1988_3stack_ch6_init }, 2137 }; 2138 2139 static struct hda_verb ad1988_3stack_init_verbs[] = { 2140 /* Front, Surround, CLFE, side DAC; unmute as default */ 2141 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2142 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2143 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2144 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2145 /* Port-A front headphon path */ 2146 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */ 2147 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2148 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2149 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2150 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2151 /* Port-D line-out path */ 2152 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2153 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2154 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2155 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2156 /* Mono out path */ 2157 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2158 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2159 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2160 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2161 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2162 /* Port-B front mic-in path */ 2163 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2164 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2165 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2166 /* Port-C line-in/surround path - 6ch mode as default */ 2167 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2168 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2169 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2170 {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */ 2171 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2172 /* Port-E mic-in/CLFE path - 6ch mode as default */ 2173 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2174 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2175 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2176 {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */ 2177 {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, 2178 /* mute analog mix */ 2179 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2180 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2181 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2182 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2183 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2184 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2185 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2186 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2187 /* select ADCs - front-mic */ 2188 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2189 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2190 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2191 /* ADCs; muted */ 2192 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2193 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2194 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2195 { } 2196 }; 2197 2198 /* 2199 * verbs for laptop mode (+dig) 2200 */ 2201 static struct hda_verb ad1988_laptop_hp_on[] = { 2202 /* unmute port-A and mute port-D */ 2203 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2204 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2205 { } /* end */ 2206 }; 2207 static struct hda_verb ad1988_laptop_hp_off[] = { 2208 /* mute port-A and unmute port-D */ 2209 { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2210 { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, 2211 { } /* end */ 2212 }; 2213 2214 #define AD1988_HP_EVENT 0x01 2215 2216 static struct hda_verb ad1988_laptop_init_verbs[] = { 2217 /* Front, Surround, CLFE, side DAC; unmute as default */ 2218 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2219 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2220 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2221 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2222 /* Port-A front headphon path */ 2223 {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */ 2224 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2225 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2226 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2227 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2228 /* unsolicited event for pin-sense */ 2229 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT }, 2230 /* Port-D line-out path + EAPD */ 2231 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2232 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2233 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2234 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2235 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */ 2236 /* Mono out path */ 2237 {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ 2238 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2239 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2240 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2241 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ 2242 /* Port-B mic-in path */ 2243 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2244 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2245 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2246 /* Port-C docking station - try to output */ 2247 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2248 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2249 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2250 {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, 2251 /* mute analog mix */ 2252 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2253 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2254 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2255 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2256 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2257 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 2258 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 2259 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 2260 /* select ADCs - mic */ 2261 {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, 2262 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, 2263 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2264 /* ADCs; muted */ 2265 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2266 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2267 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2268 { } 2269 }; 2270 2271 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) 2272 { 2273 if ((res >> 26) != AD1988_HP_EVENT) 2274 return; 2275 if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31)) 2276 snd_hda_sequence_write(codec, ad1988_laptop_hp_on); 2277 else 2278 snd_hda_sequence_write(codec, ad1988_laptop_hp_off); 2279 } 2280 2281 #ifdef CONFIG_SND_HDA_POWER_SAVE 2282 static struct hda_amp_list ad1988_loopbacks[] = { 2283 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 2284 { 0x20, HDA_INPUT, 1 }, /* Line */ 2285 { 0x20, HDA_INPUT, 4 }, /* Mic */ 2286 { 0x20, HDA_INPUT, 6 }, /* CD */ 2287 { } /* end */ 2288 }; 2289 #endif 2290 2291 /* 2292 * Automatic parse of I/O pins from the BIOS configuration 2293 */ 2294 2295 #define NUM_CONTROL_ALLOC 32 2296 #define NUM_VERB_ALLOC 32 2297 2298 enum { 2299 AD_CTL_WIDGET_VOL, 2300 AD_CTL_WIDGET_MUTE, 2301 AD_CTL_BIND_MUTE, 2302 }; 2303 static struct snd_kcontrol_new ad1988_control_templates[] = { 2304 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 2305 HDA_CODEC_MUTE(NULL, 0, 0, 0), 2306 HDA_BIND_MUTE(NULL, 0, 0, 0), 2307 }; 2308 2309 /* add dynamic controls */ 2310 static int add_control(struct ad198x_spec *spec, int type, const char *name, 2311 unsigned long val) 2312 { 2313 struct snd_kcontrol_new *knew; 2314 2315 if (spec->num_kctl_used >= spec->num_kctl_alloc) { 2316 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; 2317 2318 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ 2319 if (! knew) 2320 return -ENOMEM; 2321 if (spec->kctl_alloc) { 2322 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); 2323 kfree(spec->kctl_alloc); 2324 } 2325 spec->kctl_alloc = knew; 2326 spec->num_kctl_alloc = num; 2327 } 2328 2329 knew = &spec->kctl_alloc[spec->num_kctl_used]; 2330 *knew = ad1988_control_templates[type]; 2331 knew->name = kstrdup(name, GFP_KERNEL); 2332 if (! knew->name) 2333 return -ENOMEM; 2334 knew->private_value = val; 2335 spec->num_kctl_used++; 2336 return 0; 2337 } 2338 2339 #define AD1988_PIN_CD_NID 0x18 2340 #define AD1988_PIN_BEEP_NID 0x10 2341 2342 static hda_nid_t ad1988_mixer_nids[8] = { 2343 /* A B C D E F G H */ 2344 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28 2345 }; 2346 2347 static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx) 2348 { 2349 static hda_nid_t idx_to_dac[8] = { 2350 /* A B C D E F G H */ 2351 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a 2352 }; 2353 static hda_nid_t idx_to_dac_rev2[8] = { 2354 /* A B C D E F G H */ 2355 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06 2356 }; 2357 if (is_rev2(codec)) 2358 return idx_to_dac_rev2[idx]; 2359 else 2360 return idx_to_dac[idx]; 2361 } 2362 2363 static hda_nid_t ad1988_boost_nids[8] = { 2364 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0 2365 }; 2366 2367 static int ad1988_pin_idx(hda_nid_t nid) 2368 { 2369 static hda_nid_t ad1988_io_pins[8] = { 2370 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25 2371 }; 2372 int i; 2373 for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++) 2374 if (ad1988_io_pins[i] == nid) 2375 return i; 2376 return 0; /* should be -1 */ 2377 } 2378 2379 static int ad1988_pin_to_loopback_idx(hda_nid_t nid) 2380 { 2381 static int loopback_idx[8] = { 2382 2, 0, 1, 3, 4, 5, 1, 4 2383 }; 2384 switch (nid) { 2385 case AD1988_PIN_CD_NID: 2386 return 6; 2387 default: 2388 return loopback_idx[ad1988_pin_idx(nid)]; 2389 } 2390 } 2391 2392 static int ad1988_pin_to_adc_idx(hda_nid_t nid) 2393 { 2394 static int adc_idx[8] = { 2395 0, 1, 2, 8, 4, 3, 6, 7 2396 }; 2397 switch (nid) { 2398 case AD1988_PIN_CD_NID: 2399 return 5; 2400 default: 2401 return adc_idx[ad1988_pin_idx(nid)]; 2402 } 2403 } 2404 2405 /* fill in the dac_nids table from the parsed pin configuration */ 2406 static int ad1988_auto_fill_dac_nids(struct hda_codec *codec, 2407 const struct auto_pin_cfg *cfg) 2408 { 2409 struct ad198x_spec *spec = codec->spec; 2410 int i, idx; 2411 2412 spec->multiout.dac_nids = spec->private_dac_nids; 2413 2414 /* check the pins hardwired to audio widget */ 2415 for (i = 0; i < cfg->line_outs; i++) { 2416 idx = ad1988_pin_idx(cfg->line_out_pins[i]); 2417 spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx); 2418 } 2419 spec->multiout.num_dacs = cfg->line_outs; 2420 return 0; 2421 } 2422 2423 /* add playback controls from the parsed DAC table */ 2424 static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec, 2425 const struct auto_pin_cfg *cfg) 2426 { 2427 char name[32]; 2428 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; 2429 hda_nid_t nid; 2430 int i, err; 2431 2432 for (i = 0; i < cfg->line_outs; i++) { 2433 hda_nid_t dac = spec->multiout.dac_nids[i]; 2434 if (! dac) 2435 continue; 2436 nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])]; 2437 if (i == 2) { 2438 /* Center/LFE */ 2439 err = add_control(spec, AD_CTL_WIDGET_VOL, 2440 "Center Playback Volume", 2441 HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT)); 2442 if (err < 0) 2443 return err; 2444 err = add_control(spec, AD_CTL_WIDGET_VOL, 2445 "LFE Playback Volume", 2446 HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT)); 2447 if (err < 0) 2448 return err; 2449 err = add_control(spec, AD_CTL_BIND_MUTE, 2450 "Center Playback Switch", 2451 HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT)); 2452 if (err < 0) 2453 return err; 2454 err = add_control(spec, AD_CTL_BIND_MUTE, 2455 "LFE Playback Switch", 2456 HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT)); 2457 if (err < 0) 2458 return err; 2459 } else { 2460 sprintf(name, "%s Playback Volume", chname[i]); 2461 err = add_control(spec, AD_CTL_WIDGET_VOL, name, 2462 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT)); 2463 if (err < 0) 2464 return err; 2465 sprintf(name, "%s Playback Switch", chname[i]); 2466 err = add_control(spec, AD_CTL_BIND_MUTE, name, 2467 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); 2468 if (err < 0) 2469 return err; 2470 } 2471 } 2472 return 0; 2473 } 2474 2475 /* add playback controls for speaker and HP outputs */ 2476 static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, 2477 const char *pfx) 2478 { 2479 struct ad198x_spec *spec = codec->spec; 2480 hda_nid_t nid; 2481 int idx, err; 2482 char name[32]; 2483 2484 if (! pin) 2485 return 0; 2486 2487 idx = ad1988_pin_idx(pin); 2488 nid = ad1988_idx_to_dac(codec, idx); 2489 /* specify the DAC as the extra output */ 2490 if (! spec->multiout.hp_nid) 2491 spec->multiout.hp_nid = nid; 2492 else 2493 spec->multiout.extra_out_nid[0] = nid; 2494 /* control HP volume/switch on the output mixer amp */ 2495 sprintf(name, "%s Playback Volume", pfx); 2496 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, 2497 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) 2498 return err; 2499 nid = ad1988_mixer_nids[idx]; 2500 sprintf(name, "%s Playback Switch", pfx); 2501 if ((err = add_control(spec, AD_CTL_BIND_MUTE, name, 2502 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) 2503 return err; 2504 return 0; 2505 } 2506 2507 /* create input playback/capture controls for the given pin */ 2508 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, 2509 const char *ctlname, int boost) 2510 { 2511 char name[32]; 2512 int err, idx; 2513 2514 sprintf(name, "%s Playback Volume", ctlname); 2515 idx = ad1988_pin_to_loopback_idx(pin); 2516 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, 2517 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0) 2518 return err; 2519 sprintf(name, "%s Playback Switch", ctlname); 2520 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name, 2521 HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0) 2522 return err; 2523 if (boost) { 2524 hda_nid_t bnid; 2525 idx = ad1988_pin_idx(pin); 2526 bnid = ad1988_boost_nids[idx]; 2527 if (bnid) { 2528 sprintf(name, "%s Boost", ctlname); 2529 return add_control(spec, AD_CTL_WIDGET_VOL, name, 2530 HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT)); 2531 2532 } 2533 } 2534 return 0; 2535 } 2536 2537 /* create playback/capture controls for input pins */ 2538 static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec, 2539 const struct auto_pin_cfg *cfg) 2540 { 2541 struct hda_input_mux *imux = &spec->private_imux; 2542 int i, err; 2543 2544 for (i = 0; i < AUTO_PIN_LAST; i++) { 2545 err = new_analog_input(spec, cfg->input_pins[i], 2546 auto_pin_cfg_labels[i], 2547 i <= AUTO_PIN_FRONT_MIC); 2548 if (err < 0) 2549 return err; 2550 imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; 2551 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]); 2552 imux->num_items++; 2553 } 2554 imux->items[imux->num_items].label = "Mix"; 2555 imux->items[imux->num_items].index = 9; 2556 imux->num_items++; 2557 2558 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, 2559 "Analog Mix Playback Volume", 2560 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0) 2561 return err; 2562 if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, 2563 "Analog Mix Playback Switch", 2564 HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0) 2565 return err; 2566 2567 return 0; 2568 } 2569 2570 static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec, 2571 hda_nid_t nid, int pin_type, 2572 int dac_idx) 2573 { 2574 /* set as output */ 2575 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); 2576 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 2577 switch (nid) { 2578 case 0x11: /* port-A - DAC 04 */ 2579 snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01); 2580 break; 2581 case 0x14: /* port-B - DAC 06 */ 2582 snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02); 2583 break; 2584 case 0x15: /* port-C - DAC 05 */ 2585 snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00); 2586 break; 2587 case 0x17: /* port-E - DAC 0a */ 2588 snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01); 2589 break; 2590 case 0x13: /* mono - DAC 04 */ 2591 snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01); 2592 break; 2593 } 2594 } 2595 2596 static void ad1988_auto_init_multi_out(struct hda_codec *codec) 2597 { 2598 struct ad198x_spec *spec = codec->spec; 2599 int i; 2600 2601 for (i = 0; i < spec->autocfg.line_outs; i++) { 2602 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 2603 ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); 2604 } 2605 } 2606 2607 static void ad1988_auto_init_extra_out(struct hda_codec *codec) 2608 { 2609 struct ad198x_spec *spec = codec->spec; 2610 hda_nid_t pin; 2611 2612 pin = spec->autocfg.speaker_pins[0]; 2613 if (pin) /* connect to front */ 2614 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 2615 pin = spec->autocfg.hp_pins[0]; 2616 if (pin) /* connect to front */ 2617 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 2618 } 2619 2620 static void ad1988_auto_init_analog_input(struct hda_codec *codec) 2621 { 2622 struct ad198x_spec *spec = codec->spec; 2623 int i, idx; 2624 2625 for (i = 0; i < AUTO_PIN_LAST; i++) { 2626 hda_nid_t nid = spec->autocfg.input_pins[i]; 2627 if (! nid) 2628 continue; 2629 switch (nid) { 2630 case 0x15: /* port-C */ 2631 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); 2632 break; 2633 case 0x17: /* port-E */ 2634 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0); 2635 break; 2636 } 2637 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2638 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); 2639 if (nid != AD1988_PIN_CD_NID) 2640 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 2641 AMP_OUT_MUTE); 2642 idx = ad1988_pin_idx(nid); 2643 if (ad1988_boost_nids[idx]) 2644 snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0, 2645 AC_VERB_SET_AMP_GAIN_MUTE, 2646 AMP_OUT_ZERO); 2647 } 2648 } 2649 2650 /* parse the BIOS configuration and set up the alc_spec */ 2651 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */ 2652 static int ad1988_parse_auto_config(struct hda_codec *codec) 2653 { 2654 struct ad198x_spec *spec = codec->spec; 2655 int err; 2656 2657 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) 2658 return err; 2659 if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) 2660 return err; 2661 if (! spec->autocfg.line_outs) 2662 return 0; /* can't find valid BIOS pin config */ 2663 if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || 2664 (err = ad1988_auto_create_extra_out(codec, 2665 spec->autocfg.speaker_pins[0], 2666 "Speaker")) < 0 || 2667 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], 2668 "Headphone")) < 0 || 2669 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) 2670 return err; 2671 2672 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 2673 2674 if (spec->autocfg.dig_out_pin) 2675 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 2676 if (spec->autocfg.dig_in_pin) 2677 spec->dig_in_nid = AD1988_SPDIF_IN; 2678 2679 if (spec->kctl_alloc) 2680 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 2681 2682 spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; 2683 2684 spec->input_mux = &spec->private_imux; 2685 2686 return 1; 2687 } 2688 2689 /* init callback for auto-configuration model -- overriding the default init */ 2690 static int ad1988_auto_init(struct hda_codec *codec) 2691 { 2692 ad198x_init(codec); 2693 ad1988_auto_init_multi_out(codec); 2694 ad1988_auto_init_extra_out(codec); 2695 ad1988_auto_init_analog_input(codec); 2696 return 0; 2697 } 2698 2699 2700 /* 2701 */ 2702 2703 static const char *ad1988_models[AD1988_MODEL_LAST] = { 2704 [AD1988_6STACK] = "6stack", 2705 [AD1988_6STACK_DIG] = "6stack-dig", 2706 [AD1988_3STACK] = "3stack", 2707 [AD1988_3STACK_DIG] = "3stack-dig", 2708 [AD1988_LAPTOP] = "laptop", 2709 [AD1988_LAPTOP_DIG] = "laptop-dig", 2710 [AD1988_AUTO] = "auto", 2711 }; 2712 2713 static struct snd_pci_quirk ad1988_cfg_tbl[] = { 2714 SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG), 2715 SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG), 2716 {} 2717 }; 2718 2719 static int patch_ad1988(struct hda_codec *codec) 2720 { 2721 struct ad198x_spec *spec; 2722 int board_config; 2723 2724 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 2725 if (spec == NULL) 2726 return -ENOMEM; 2727 2728 codec->spec = spec; 2729 2730 if (is_rev2(codec)) 2731 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); 2732 2733 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST, 2734 ad1988_models, ad1988_cfg_tbl); 2735 if (board_config < 0) { 2736 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n"); 2737 board_config = AD1988_AUTO; 2738 } 2739 2740 if (board_config == AD1988_AUTO) { 2741 /* automatic parse from the BIOS config */ 2742 int err = ad1988_parse_auto_config(codec); 2743 if (err < 0) { 2744 ad198x_free(codec); 2745 return err; 2746 } else if (! err) { 2747 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n"); 2748 board_config = AD1988_6STACK; 2749 } 2750 } 2751 2752 switch (board_config) { 2753 case AD1988_6STACK: 2754 case AD1988_6STACK_DIG: 2755 spec->multiout.max_channels = 8; 2756 spec->multiout.num_dacs = 4; 2757 if (is_rev2(codec)) 2758 spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2; 2759 else 2760 spec->multiout.dac_nids = ad1988_6stack_dac_nids; 2761 spec->input_mux = &ad1988_6stack_capture_source; 2762 spec->num_mixers = 2; 2763 if (is_rev2(codec)) 2764 spec->mixers[0] = ad1988_6stack_mixers1_rev2; 2765 else 2766 spec->mixers[0] = ad1988_6stack_mixers1; 2767 spec->mixers[1] = ad1988_6stack_mixers2; 2768 spec->num_init_verbs = 1; 2769 spec->init_verbs[0] = ad1988_6stack_init_verbs; 2770 if (board_config == AD1988_6STACK_DIG) { 2771 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 2772 spec->dig_in_nid = AD1988_SPDIF_IN; 2773 } 2774 break; 2775 case AD1988_3STACK: 2776 case AD1988_3STACK_DIG: 2777 spec->multiout.max_channels = 6; 2778 spec->multiout.num_dacs = 3; 2779 if (is_rev2(codec)) 2780 spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2; 2781 else 2782 spec->multiout.dac_nids = ad1988_3stack_dac_nids; 2783 spec->input_mux = &ad1988_6stack_capture_source; 2784 spec->channel_mode = ad1988_3stack_modes; 2785 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes); 2786 spec->num_mixers = 2; 2787 if (is_rev2(codec)) 2788 spec->mixers[0] = ad1988_3stack_mixers1_rev2; 2789 else 2790 spec->mixers[0] = ad1988_3stack_mixers1; 2791 spec->mixers[1] = ad1988_3stack_mixers2; 2792 spec->num_init_verbs = 1; 2793 spec->init_verbs[0] = ad1988_3stack_init_verbs; 2794 if (board_config == AD1988_3STACK_DIG) 2795 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 2796 break; 2797 case AD1988_LAPTOP: 2798 case AD1988_LAPTOP_DIG: 2799 spec->multiout.max_channels = 2; 2800 spec->multiout.num_dacs = 1; 2801 spec->multiout.dac_nids = ad1988_3stack_dac_nids; 2802 spec->input_mux = &ad1988_laptop_capture_source; 2803 spec->num_mixers = 1; 2804 spec->mixers[0] = ad1988_laptop_mixers; 2805 spec->num_init_verbs = 1; 2806 spec->init_verbs[0] = ad1988_laptop_init_verbs; 2807 if (board_config == AD1988_LAPTOP_DIG) 2808 spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; 2809 break; 2810 } 2811 2812 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids); 2813 spec->adc_nids = ad1988_adc_nids; 2814 spec->capsrc_nids = ad1988_capsrc_nids; 2815 spec->mixers[spec->num_mixers++] = ad1988_capture_mixers; 2816 spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs; 2817 if (spec->multiout.dig_out_nid) { 2818 spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers; 2819 spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs; 2820 } 2821 if (spec->dig_in_nid) 2822 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; 2823 2824 codec->patch_ops = ad198x_patch_ops; 2825 switch (board_config) { 2826 case AD1988_AUTO: 2827 codec->patch_ops.init = ad1988_auto_init; 2828 break; 2829 case AD1988_LAPTOP: 2830 case AD1988_LAPTOP_DIG: 2831 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; 2832 break; 2833 } 2834 #ifdef CONFIG_SND_HDA_POWER_SAVE 2835 spec->loopback.amplist = ad1988_loopbacks; 2836 #endif 2837 2838 return 0; 2839 } 2840 2841 2842 /* 2843 * AD1884 / AD1984 2844 * 2845 * port-B - front line/mic-in 2846 * port-E - aux in/out 2847 * port-F - aux in/out 2848 * port-C - rear line/mic-in 2849 * port-D - rear line/hp-out 2850 * port-A - front line/hp-out 2851 * 2852 * AD1984 = AD1884 + two digital mic-ins 2853 * 2854 * FIXME: 2855 * For simplicity, we share the single DAC for both HP and line-outs 2856 * right now. The inidividual playbacks could be easily implemented, 2857 * but no build-up framework is given, so far. 2858 */ 2859 2860 static hda_nid_t ad1884_dac_nids[1] = { 2861 0x04, 2862 }; 2863 2864 static hda_nid_t ad1884_adc_nids[2] = { 2865 0x08, 0x09, 2866 }; 2867 2868 static hda_nid_t ad1884_capsrc_nids[2] = { 2869 0x0c, 0x0d, 2870 }; 2871 2872 #define AD1884_SPDIF_OUT 0x02 2873 2874 static struct hda_input_mux ad1884_capture_source = { 2875 .num_items = 4, 2876 .items = { 2877 { "Front Mic", 0x0 }, 2878 { "Mic", 0x1 }, 2879 { "CD", 0x2 }, 2880 { "Mix", 0x3 }, 2881 }, 2882 }; 2883 2884 static struct snd_kcontrol_new ad1884_base_mixers[] = { 2885 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 2886 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ 2887 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 2888 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 2889 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 2890 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 2891 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 2892 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 2893 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 2894 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 2895 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), 2896 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), 2897 /* 2898 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT), 2899 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT), 2900 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), 2901 HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), 2902 */ 2903 HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), 2904 HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), 2905 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 2906 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 2907 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 2908 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 2909 { 2910 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2911 /* The multiple "Capture Source" controls confuse alsamixer 2912 * So call somewhat different.. 2913 * FIXME: the controls appear in the "playback" view! 2914 */ 2915 /* .name = "Capture Source", */ 2916 .name = "Input Source", 2917 .count = 2, 2918 .info = ad198x_mux_enum_info, 2919 .get = ad198x_mux_enum_get, 2920 .put = ad198x_mux_enum_put, 2921 }, 2922 /* SPDIF controls */ 2923 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 2924 { 2925 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2926 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 2927 /* identical with ad1983 */ 2928 .info = ad1983_spdif_route_info, 2929 .get = ad1983_spdif_route_get, 2930 .put = ad1983_spdif_route_put, 2931 }, 2932 { } /* end */ 2933 }; 2934 2935 static struct snd_kcontrol_new ad1984_dmic_mixers[] = { 2936 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT), 2937 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT), 2938 HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0, 2939 HDA_INPUT), 2940 HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0, 2941 HDA_INPUT), 2942 { } /* end */ 2943 }; 2944 2945 /* 2946 * initialization verbs 2947 */ 2948 static struct hda_verb ad1884_init_verbs[] = { 2949 /* DACs; mute as default */ 2950 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2951 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 2952 /* Port-A (HP) mixer */ 2953 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2954 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2955 /* Port-A pin */ 2956 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2957 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2958 /* HP selector - select DAC2 */ 2959 {0x22, AC_VERB_SET_CONNECT_SEL, 0x1}, 2960 /* Port-D (Line-out) mixer */ 2961 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2962 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2963 /* Port-D pin */ 2964 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2965 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2966 /* Mono-out mixer */ 2967 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 2968 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 2969 /* Mono-out pin */ 2970 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2971 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2972 /* Mono selector */ 2973 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, 2974 /* Port-B (front mic) pin */ 2975 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2976 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2977 /* Port-C (rear mic) pin */ 2978 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2979 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2980 /* Analog mixer; mute as default */ 2981 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2982 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2983 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2984 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2985 /* Analog Mix output amp */ 2986 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 2987 /* SPDIF output selector */ 2988 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 2989 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 2990 { } /* end */ 2991 }; 2992 2993 #ifdef CONFIG_SND_HDA_POWER_SAVE 2994 static struct hda_amp_list ad1884_loopbacks[] = { 2995 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 2996 { 0x20, HDA_INPUT, 1 }, /* Mic */ 2997 { 0x20, HDA_INPUT, 2 }, /* CD */ 2998 { 0x20, HDA_INPUT, 4 }, /* Docking */ 2999 { } /* end */ 3000 }; 3001 #endif 3002 3003 static int patch_ad1884(struct hda_codec *codec) 3004 { 3005 struct ad198x_spec *spec; 3006 3007 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3008 if (spec == NULL) 3009 return -ENOMEM; 3010 3011 mutex_init(&spec->amp_mutex); 3012 codec->spec = spec; 3013 3014 spec->multiout.max_channels = 2; 3015 spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); 3016 spec->multiout.dac_nids = ad1884_dac_nids; 3017 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; 3018 spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids); 3019 spec->adc_nids = ad1884_adc_nids; 3020 spec->capsrc_nids = ad1884_capsrc_nids; 3021 spec->input_mux = &ad1884_capture_source; 3022 spec->num_mixers = 1; 3023 spec->mixers[0] = ad1884_base_mixers; 3024 spec->num_init_verbs = 1; 3025 spec->init_verbs[0] = ad1884_init_verbs; 3026 spec->spdif_route = 0; 3027 #ifdef CONFIG_SND_HDA_POWER_SAVE 3028 spec->loopback.amplist = ad1884_loopbacks; 3029 #endif 3030 3031 codec->patch_ops = ad198x_patch_ops; 3032 3033 return 0; 3034 } 3035 3036 /* 3037 * Lenovo Thinkpad T61/X61 3038 */ 3039 static struct hda_input_mux ad1984_thinkpad_capture_source = { 3040 .num_items = 3, 3041 .items = { 3042 { "Mic", 0x0 }, 3043 { "Internal Mic", 0x1 }, 3044 { "Mix", 0x3 }, 3045 }, 3046 }; 3047 3048 static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { 3049 HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3050 /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ 3051 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3052 HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3053 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3054 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3055 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3056 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3057 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 3058 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 3059 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), 3060 HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), 3061 HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT), 3062 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), 3063 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), 3064 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3065 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3066 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3067 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3068 { 3069 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3070 /* The multiple "Capture Source" controls confuse alsamixer 3071 * So call somewhat different.. 3072 * FIXME: the controls appear in the "playback" view! 3073 */ 3074 /* .name = "Capture Source", */ 3075 .name = "Input Source", 3076 .count = 2, 3077 .info = ad198x_mux_enum_info, 3078 .get = ad198x_mux_enum_get, 3079 .put = ad198x_mux_enum_put, 3080 }, 3081 { } /* end */ 3082 }; 3083 3084 /* additional verbs */ 3085 static struct hda_verb ad1984_thinkpad_init_verbs[] = { 3086 /* Port-E (docking station mic) pin */ 3087 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3088 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3089 /* docking mic boost */ 3090 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3091 /* Analog mixer - docking mic; mute as default */ 3092 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3093 /* enable EAPD bit */ 3094 {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 3095 { } /* end */ 3096 }; 3097 3098 /* Digial MIC ADC NID 0x05 + 0x06 */ 3099 static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo, 3100 struct hda_codec *codec, 3101 unsigned int stream_tag, 3102 unsigned int format, 3103 struct snd_pcm_substream *substream) 3104 { 3105 snd_hda_codec_setup_stream(codec, 0x05 + substream->number, 3106 stream_tag, 0, format); 3107 return 0; 3108 } 3109 3110 static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo, 3111 struct hda_codec *codec, 3112 struct snd_pcm_substream *substream) 3113 { 3114 snd_hda_codec_setup_stream(codec, 0x05 + substream->number, 3115 0, 0, 0); 3116 return 0; 3117 } 3118 3119 static struct hda_pcm_stream ad1984_pcm_dmic_capture = { 3120 .substreams = 2, 3121 .channels_min = 2, 3122 .channels_max = 2, 3123 .nid = 0x05, 3124 .ops = { 3125 .prepare = ad1984_pcm_dmic_prepare, 3126 .cleanup = ad1984_pcm_dmic_cleanup 3127 }, 3128 }; 3129 3130 static int ad1984_build_pcms(struct hda_codec *codec) 3131 { 3132 struct ad198x_spec *spec = codec->spec; 3133 struct hda_pcm *info; 3134 int err; 3135 3136 err = ad198x_build_pcms(codec); 3137 if (err < 0) 3138 return err; 3139 3140 info = spec->pcm_rec + codec->num_pcms; 3141 codec->num_pcms++; 3142 info->name = "AD1984 Digital Mic"; 3143 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture; 3144 return 0; 3145 } 3146 3147 /* models */ 3148 enum { 3149 AD1984_BASIC, 3150 AD1984_THINKPAD, 3151 AD1984_MODELS 3152 }; 3153 3154 static const char *ad1984_models[AD1984_MODELS] = { 3155 [AD1984_BASIC] = "basic", 3156 [AD1984_THINKPAD] = "thinkpad", 3157 }; 3158 3159 static struct snd_pci_quirk ad1984_cfg_tbl[] = { 3160 /* Lenovo Thinkpad T61/X61 */ 3161 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD), 3162 {} 3163 }; 3164 3165 static int patch_ad1984(struct hda_codec *codec) 3166 { 3167 struct ad198x_spec *spec; 3168 int board_config, err; 3169 3170 err = patch_ad1884(codec); 3171 if (err < 0) 3172 return err; 3173 spec = codec->spec; 3174 board_config = snd_hda_check_board_config(codec, AD1984_MODELS, 3175 ad1984_models, ad1984_cfg_tbl); 3176 switch (board_config) { 3177 case AD1984_BASIC: 3178 /* additional digital mics */ 3179 spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers; 3180 codec->patch_ops.build_pcms = ad1984_build_pcms; 3181 break; 3182 case AD1984_THINKPAD: 3183 spec->multiout.dig_out_nid = 0; 3184 spec->input_mux = &ad1984_thinkpad_capture_source; 3185 spec->mixers[0] = ad1984_thinkpad_mixers; 3186 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; 3187 break; 3188 } 3189 return 0; 3190 } 3191 3192 3193 /* 3194 * AD1882 3195 * 3196 * port-A - front hp-out 3197 * port-B - front mic-in 3198 * port-C - rear line-in, shared surr-out (3stack) 3199 * port-D - rear line-out 3200 * port-E - rear mic-in, shared clfe-out (3stack) 3201 * port-F - rear surr-out (6stack) 3202 * port-G - rear clfe-out (6stack) 3203 */ 3204 3205 static hda_nid_t ad1882_dac_nids[3] = { 3206 0x04, 0x03, 0x05 3207 }; 3208 3209 static hda_nid_t ad1882_adc_nids[2] = { 3210 0x08, 0x09, 3211 }; 3212 3213 static hda_nid_t ad1882_capsrc_nids[2] = { 3214 0x0c, 0x0d, 3215 }; 3216 3217 #define AD1882_SPDIF_OUT 0x02 3218 3219 /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */ 3220 static struct hda_input_mux ad1882_capture_source = { 3221 .num_items = 5, 3222 .items = { 3223 { "Front Mic", 0x1 }, 3224 { "Mic", 0x4 }, 3225 { "Line", 0x2 }, 3226 { "CD", 0x3 }, 3227 { "Mix", 0x7 }, 3228 }, 3229 }; 3230 3231 static struct snd_kcontrol_new ad1882_base_mixers[] = { 3232 HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), 3233 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), 3234 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), 3235 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), 3236 HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), 3237 HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), 3238 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), 3239 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), 3240 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), 3241 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3242 HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3243 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3244 HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT), 3245 HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), 3246 HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), 3247 HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), 3248 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), 3249 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), 3250 HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT), 3251 HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT), 3252 HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT), 3253 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), 3254 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), 3255 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), 3256 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), 3257 { 3258 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3259 /* The multiple "Capture Source" controls confuse alsamixer 3260 * So call somewhat different.. 3261 * FIXME: the controls appear in the "playback" view! 3262 */ 3263 /* .name = "Capture Source", */ 3264 .name = "Input Source", 3265 .count = 2, 3266 .info = ad198x_mux_enum_info, 3267 .get = ad198x_mux_enum_get, 3268 .put = ad198x_mux_enum_put, 3269 }, 3270 /* SPDIF controls */ 3271 HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 3272 { 3273 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3274 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", 3275 /* identical with ad1983 */ 3276 .info = ad1983_spdif_route_info, 3277 .get = ad1983_spdif_route_get, 3278 .put = ad1983_spdif_route_put, 3279 }, 3280 { } /* end */ 3281 }; 3282 3283 static struct snd_kcontrol_new ad1882_3stack_mixers[] = { 3284 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), 3285 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT), 3286 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT), 3287 { 3288 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3289 .name = "Channel Mode", 3290 .info = ad198x_ch_mode_info, 3291 .get = ad198x_ch_mode_get, 3292 .put = ad198x_ch_mode_put, 3293 }, 3294 { } /* end */ 3295 }; 3296 3297 static struct snd_kcontrol_new ad1882_6stack_mixers[] = { 3298 HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT), 3299 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT), 3300 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT), 3301 { } /* end */ 3302 }; 3303 3304 static struct hda_verb ad1882_ch2_init[] = { 3305 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3306 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3307 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3308 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3309 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3310 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3311 { } /* end */ 3312 }; 3313 3314 static struct hda_verb ad1882_ch4_init[] = { 3315 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3316 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3317 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3318 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3319 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3320 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3321 { } /* end */ 3322 }; 3323 3324 static struct hda_verb ad1882_ch6_init[] = { 3325 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3326 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3327 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3328 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3329 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3330 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3331 { } /* end */ 3332 }; 3333 3334 static struct hda_channel_mode ad1882_modes[3] = { 3335 { 2, ad1882_ch2_init }, 3336 { 4, ad1882_ch4_init }, 3337 { 6, ad1882_ch6_init }, 3338 }; 3339 3340 /* 3341 * initialization verbs 3342 */ 3343 static struct hda_verb ad1882_init_verbs[] = { 3344 /* DACs; mute as default */ 3345 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3346 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3347 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3348 /* Port-A (HP) mixer */ 3349 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3350 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3351 /* Port-A pin */ 3352 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3353 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3354 /* HP selector - select DAC2 */ 3355 {0x37, AC_VERB_SET_CONNECT_SEL, 0x1}, 3356 /* Port-D (Line-out) mixer */ 3357 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3358 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3359 /* Port-D pin */ 3360 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3361 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3362 /* Mono-out mixer */ 3363 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 3364 {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 3365 /* Mono-out pin */ 3366 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 3367 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3368 /* Port-B (front mic) pin */ 3369 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3370 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3371 {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 3372 /* Port-C (line-in) pin */ 3373 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3374 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3375 {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 3376 /* Port-C mixer - mute as input */ 3377 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3378 {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3379 /* Port-E (mic-in) pin */ 3380 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 3381 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3382 {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ 3383 /* Port-E mixer - mute as input */ 3384 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3385 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3386 /* Port-F (surround) */ 3387 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3388 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3389 /* Port-G (CLFE) */ 3390 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3391 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3392 /* Analog mixer; mute as default */ 3393 /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */ 3394 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3395 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 3396 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 3397 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 3398 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3399 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, 3400 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, 3401 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, 3402 /* Analog Mix output amp */ 3403 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ 3404 /* SPDIF output selector */ 3405 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 3406 {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ 3407 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ 3408 { } /* end */ 3409 }; 3410 3411 #ifdef CONFIG_SND_HDA_POWER_SAVE 3412 static struct hda_amp_list ad1882_loopbacks[] = { 3413 { 0x20, HDA_INPUT, 0 }, /* Front Mic */ 3414 { 0x20, HDA_INPUT, 1 }, /* Mic */ 3415 { 0x20, HDA_INPUT, 4 }, /* Line */ 3416 { 0x20, HDA_INPUT, 6 }, /* CD */ 3417 { } /* end */ 3418 }; 3419 #endif 3420 3421 /* models */ 3422 enum { 3423 AD1882_3STACK, 3424 AD1882_6STACK, 3425 AD1882_MODELS 3426 }; 3427 3428 static const char *ad1882_models[AD1986A_MODELS] = { 3429 [AD1882_3STACK] = "3stack", 3430 [AD1882_6STACK] = "6stack", 3431 }; 3432 3433 3434 static int patch_ad1882(struct hda_codec *codec) 3435 { 3436 struct ad198x_spec *spec; 3437 int board_config; 3438 3439 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3440 if (spec == NULL) 3441 return -ENOMEM; 3442 3443 mutex_init(&spec->amp_mutex); 3444 codec->spec = spec; 3445 3446 spec->multiout.max_channels = 6; 3447 spec->multiout.num_dacs = 3; 3448 spec->multiout.dac_nids = ad1882_dac_nids; 3449 spec->multiout.dig_out_nid = AD1882_SPDIF_OUT; 3450 spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids); 3451 spec->adc_nids = ad1882_adc_nids; 3452 spec->capsrc_nids = ad1882_capsrc_nids; 3453 spec->input_mux = &ad1882_capture_source; 3454 spec->num_mixers = 1; 3455 spec->mixers[0] = ad1882_base_mixers; 3456 spec->num_init_verbs = 1; 3457 spec->init_verbs[0] = ad1882_init_verbs; 3458 spec->spdif_route = 0; 3459 #ifdef CONFIG_SND_HDA_POWER_SAVE 3460 spec->loopback.amplist = ad1882_loopbacks; 3461 #endif 3462 3463 codec->patch_ops = ad198x_patch_ops; 3464 3465 /* override some parameters */ 3466 board_config = snd_hda_check_board_config(codec, AD1882_MODELS, 3467 ad1882_models, NULL); 3468 switch (board_config) { 3469 default: 3470 case AD1882_3STACK: 3471 spec->num_mixers = 2; 3472 spec->mixers[1] = ad1882_3stack_mixers; 3473 spec->channel_mode = ad1882_modes; 3474 spec->num_channel_mode = ARRAY_SIZE(ad1882_modes); 3475 spec->need_dac_fix = 1; 3476 spec->multiout.max_channels = 2; 3477 spec->multiout.num_dacs = 1; 3478 break; 3479 case AD1882_6STACK: 3480 spec->num_mixers = 2; 3481 spec->mixers[1] = ad1882_6stack_mixers; 3482 break; 3483 } 3484 return 0; 3485 } 3486 3487 3488 /* 3489 * patch entries 3490 */ 3491 struct hda_codec_preset snd_hda_preset_analog[] = { 3492 { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 }, 3493 { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 }, 3494 { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, 3495 { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, 3496 { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 }, 3497 { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, 3498 { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, 3499 { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, 3500 {} /* terminator */ 3501 }; 3502