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