1 /* 2 * HD audio interface patch for Conexant HDA audio codec 3 * 4 * Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com> 5 * Takashi Iwai <tiwai@suse.de> 6 * Tobin Davis <tdavis@dsl-only.net> 7 * 8 * This driver is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This driver is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 #include <linux/init.h> 24 #include <linux/delay.h> 25 #include <linux/slab.h> 26 #include <linux/pci.h> 27 #include <linux/module.h> 28 #include <sound/core.h> 29 #include <sound/jack.h> 30 31 #include "hda_codec.h" 32 #include "hda_local.h" 33 #include "hda_auto_parser.h" 34 #include "hda_beep.h" 35 #include "hda_jack.h" 36 #include "hda_generic.h" 37 38 #define ENABLE_CXT_STATIC_QUIRKS 39 40 #define CXT_PIN_DIR_IN 0x00 41 #define CXT_PIN_DIR_OUT 0x01 42 #define CXT_PIN_DIR_INOUT 0x02 43 #define CXT_PIN_DIR_IN_NOMICBIAS 0x03 44 #define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04 45 46 #define CONEXANT_HP_EVENT 0x37 47 #define CONEXANT_MIC_EVENT 0x38 48 #define CONEXANT_LINE_EVENT 0x39 49 50 /* Conexant 5051 specific */ 51 52 #define CXT5051_SPDIF_OUT 0x12 53 #define CXT5051_PORTB_EVENT 0x38 54 #define CXT5051_PORTC_EVENT 0x39 55 56 #define AUTO_MIC_PORTB (1 << 1) 57 #define AUTO_MIC_PORTC (1 << 2) 58 59 struct conexant_spec { 60 struct hda_gen_spec gen; 61 62 unsigned int beep_amp; 63 64 /* extra EAPD pins */ 65 unsigned int num_eapds; 66 hda_nid_t eapds[4]; 67 68 #ifdef ENABLE_CXT_STATIC_QUIRKS 69 const struct snd_kcontrol_new *mixers[5]; 70 int num_mixers; 71 hda_nid_t vmaster_nid; 72 73 const struct hda_verb *init_verbs[5]; /* initialization verbs 74 * don't forget NULL 75 * termination! 76 */ 77 unsigned int num_init_verbs; 78 79 /* playback */ 80 struct hda_multi_out multiout; /* playback set-up 81 * max_channels, dacs must be set 82 * dig_out_nid and hp_nid are optional 83 */ 84 unsigned int cur_eapd; 85 unsigned int hp_present; 86 unsigned int line_present; 87 unsigned int auto_mic; 88 89 /* capture */ 90 unsigned int num_adc_nids; 91 const hda_nid_t *adc_nids; 92 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 93 94 unsigned int cur_adc_idx; 95 hda_nid_t cur_adc; 96 unsigned int cur_adc_stream_tag; 97 unsigned int cur_adc_format; 98 99 const struct hda_pcm_stream *capture_stream; 100 101 /* capture source */ 102 const struct hda_input_mux *input_mux; 103 const hda_nid_t *capsrc_nids; 104 unsigned int cur_mux[3]; 105 106 /* channel model */ 107 const struct hda_channel_mode *channel_mode; 108 int num_channel_mode; 109 110 /* PCM information */ 111 struct hda_pcm pcm_rec[2]; /* used in build_pcms() */ 112 113 unsigned int spdif_route; 114 115 unsigned int port_d_mode; 116 unsigned int dell_automute:1; 117 unsigned int dell_vostro:1; 118 unsigned int ideapad:1; 119 unsigned int thinkpad:1; 120 unsigned int hp_laptop:1; 121 unsigned int asus:1; 122 123 unsigned int ext_mic_present; 124 unsigned int recording; 125 void (*capture_prepare)(struct hda_codec *codec); 126 void (*capture_cleanup)(struct hda_codec *codec); 127 128 /* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors) 129 * through the microphone jack. 130 * When the user enables this through a mixer switch, both internal and 131 * external microphones are disabled. Gain is fixed at 0dB. In this mode, 132 * we also allow the bias to be configured through a separate mixer 133 * control. */ 134 unsigned int dc_enable; 135 unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */ 136 unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ 137 #endif /* ENABLE_CXT_STATIC_QUIRKS */ 138 }; 139 140 141 #ifdef CONFIG_SND_HDA_INPUT_BEEP 142 #define set_beep_amp(spec, nid, idx, dir) \ 143 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) 144 /* additional beep mixers; the actual parameters are overwritten at build */ 145 static const struct snd_kcontrol_new cxt_beep_mixer[] = { 146 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), 147 HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT), 148 { } /* end */ 149 }; 150 151 /* create beep controls if needed */ 152 static int add_beep_ctls(struct hda_codec *codec) 153 { 154 struct conexant_spec *spec = codec->spec; 155 int err; 156 157 if (spec->beep_amp) { 158 const struct snd_kcontrol_new *knew; 159 for (knew = cxt_beep_mixer; knew->name; knew++) { 160 struct snd_kcontrol *kctl; 161 kctl = snd_ctl_new1(knew, codec); 162 if (!kctl) 163 return -ENOMEM; 164 kctl->private_value = spec->beep_amp; 165 err = snd_hda_ctl_add(codec, 0, kctl); 166 if (err < 0) 167 return err; 168 } 169 } 170 return 0; 171 } 172 #else 173 #define set_beep_amp(spec, nid, idx, dir) /* NOP */ 174 #define add_beep_ctls(codec) 0 175 #endif 176 177 178 #ifdef ENABLE_CXT_STATIC_QUIRKS 179 static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, 180 struct hda_codec *codec, 181 struct snd_pcm_substream *substream) 182 { 183 struct conexant_spec *spec = codec->spec; 184 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, 185 hinfo); 186 } 187 188 static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 189 struct hda_codec *codec, 190 unsigned int stream_tag, 191 unsigned int format, 192 struct snd_pcm_substream *substream) 193 { 194 struct conexant_spec *spec = codec->spec; 195 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, 196 stream_tag, 197 format, substream); 198 } 199 200 static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 201 struct hda_codec *codec, 202 struct snd_pcm_substream *substream) 203 { 204 struct conexant_spec *spec = codec->spec; 205 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); 206 } 207 208 /* 209 * Digital out 210 */ 211 static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, 212 struct hda_codec *codec, 213 struct snd_pcm_substream *substream) 214 { 215 struct conexant_spec *spec = codec->spec; 216 return snd_hda_multi_out_dig_open(codec, &spec->multiout); 217 } 218 219 static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, 220 struct hda_codec *codec, 221 struct snd_pcm_substream *substream) 222 { 223 struct conexant_spec *spec = codec->spec; 224 return snd_hda_multi_out_dig_close(codec, &spec->multiout); 225 } 226 227 static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 228 struct hda_codec *codec, 229 unsigned int stream_tag, 230 unsigned int format, 231 struct snd_pcm_substream *substream) 232 { 233 struct conexant_spec *spec = codec->spec; 234 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, 235 stream_tag, 236 format, substream); 237 } 238 239 /* 240 * Analog capture 241 */ 242 static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 243 struct hda_codec *codec, 244 unsigned int stream_tag, 245 unsigned int format, 246 struct snd_pcm_substream *substream) 247 { 248 struct conexant_spec *spec = codec->spec; 249 if (spec->capture_prepare) 250 spec->capture_prepare(codec); 251 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 252 stream_tag, 0, format); 253 return 0; 254 } 255 256 static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, 257 struct hda_codec *codec, 258 struct snd_pcm_substream *substream) 259 { 260 struct conexant_spec *spec = codec->spec; 261 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); 262 if (spec->capture_cleanup) 263 spec->capture_cleanup(codec); 264 return 0; 265 } 266 267 268 269 static const struct hda_pcm_stream conexant_pcm_analog_playback = { 270 .substreams = 1, 271 .channels_min = 2, 272 .channels_max = 2, 273 .nid = 0, /* fill later */ 274 .ops = { 275 .open = conexant_playback_pcm_open, 276 .prepare = conexant_playback_pcm_prepare, 277 .cleanup = conexant_playback_pcm_cleanup 278 }, 279 }; 280 281 static const struct hda_pcm_stream conexant_pcm_analog_capture = { 282 .substreams = 1, 283 .channels_min = 2, 284 .channels_max = 2, 285 .nid = 0, /* fill later */ 286 .ops = { 287 .prepare = conexant_capture_pcm_prepare, 288 .cleanup = conexant_capture_pcm_cleanup 289 }, 290 }; 291 292 293 static const struct hda_pcm_stream conexant_pcm_digital_playback = { 294 .substreams = 1, 295 .channels_min = 2, 296 .channels_max = 2, 297 .nid = 0, /* fill later */ 298 .ops = { 299 .open = conexant_dig_playback_pcm_open, 300 .close = conexant_dig_playback_pcm_close, 301 .prepare = conexant_dig_playback_pcm_prepare 302 }, 303 }; 304 305 static const struct hda_pcm_stream conexant_pcm_digital_capture = { 306 .substreams = 1, 307 .channels_min = 2, 308 .channels_max = 2, 309 /* NID is set in alc_build_pcms */ 310 }; 311 312 static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 313 struct hda_codec *codec, 314 unsigned int stream_tag, 315 unsigned int format, 316 struct snd_pcm_substream *substream) 317 { 318 struct conexant_spec *spec = codec->spec; 319 spec->cur_adc = spec->adc_nids[spec->cur_adc_idx]; 320 spec->cur_adc_stream_tag = stream_tag; 321 spec->cur_adc_format = format; 322 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); 323 return 0; 324 } 325 326 static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, 327 struct hda_codec *codec, 328 struct snd_pcm_substream *substream) 329 { 330 struct conexant_spec *spec = codec->spec; 331 snd_hda_codec_cleanup_stream(codec, spec->cur_adc); 332 spec->cur_adc = 0; 333 return 0; 334 } 335 336 static const struct hda_pcm_stream cx5051_pcm_analog_capture = { 337 .substreams = 1, 338 .channels_min = 2, 339 .channels_max = 2, 340 .nid = 0, /* fill later */ 341 .ops = { 342 .prepare = cx5051_capture_pcm_prepare, 343 .cleanup = cx5051_capture_pcm_cleanup 344 }, 345 }; 346 347 static int conexant_build_pcms(struct hda_codec *codec) 348 { 349 struct conexant_spec *spec = codec->spec; 350 struct hda_pcm *info = spec->pcm_rec; 351 352 codec->num_pcms = 1; 353 codec->pcm_info = info; 354 355 info->name = "CONEXANT Analog"; 356 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback; 357 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 358 spec->multiout.max_channels; 359 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 360 spec->multiout.dac_nids[0]; 361 if (spec->capture_stream) 362 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream; 363 else { 364 if (codec->vendor_id == 0x14f15051) 365 info->stream[SNDRV_PCM_STREAM_CAPTURE] = 366 cx5051_pcm_analog_capture; 367 else { 368 info->stream[SNDRV_PCM_STREAM_CAPTURE] = 369 conexant_pcm_analog_capture; 370 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 371 spec->num_adc_nids; 372 } 373 } 374 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; 375 376 if (spec->multiout.dig_out_nid) { 377 info++; 378 codec->num_pcms++; 379 info->name = "Conexant Digital"; 380 info->pcm_type = HDA_PCM_TYPE_SPDIF; 381 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = 382 conexant_pcm_digital_playback; 383 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 384 spec->multiout.dig_out_nid; 385 if (spec->dig_in_nid) { 386 info->stream[SNDRV_PCM_STREAM_CAPTURE] = 387 conexant_pcm_digital_capture; 388 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 389 spec->dig_in_nid; 390 } 391 } 392 393 return 0; 394 } 395 396 static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol, 397 struct snd_ctl_elem_info *uinfo) 398 { 399 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 400 struct conexant_spec *spec = codec->spec; 401 402 return snd_hda_input_mux_info(spec->input_mux, uinfo); 403 } 404 405 static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol, 406 struct snd_ctl_elem_value *ucontrol) 407 { 408 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 409 struct conexant_spec *spec = codec->spec; 410 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 411 412 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; 413 return 0; 414 } 415 416 static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, 417 struct snd_ctl_elem_value *ucontrol) 418 { 419 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 420 struct conexant_spec *spec = codec->spec; 421 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 422 423 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, 424 spec->capsrc_nids[adc_idx], 425 &spec->cur_mux[adc_idx]); 426 } 427 428 static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg, 429 unsigned int power_state) 430 { 431 if (power_state == AC_PWRST_D3) 432 msleep(100); 433 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, 434 power_state); 435 /* partial workaround for "azx_get_response timeout" */ 436 if (power_state == AC_PWRST_D0) 437 msleep(10); 438 snd_hda_codec_set_power_to_all(codec, fg, power_state); 439 } 440 441 static int conexant_init(struct hda_codec *codec) 442 { 443 struct conexant_spec *spec = codec->spec; 444 int i; 445 446 for (i = 0; i < spec->num_init_verbs; i++) 447 snd_hda_sequence_write(codec, spec->init_verbs[i]); 448 return 0; 449 } 450 451 static void conexant_free(struct hda_codec *codec) 452 { 453 struct conexant_spec *spec = codec->spec; 454 snd_hda_detach_beep_device(codec); 455 kfree(spec); 456 } 457 458 static const struct snd_kcontrol_new cxt_capture_mixers[] = { 459 { 460 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 461 .name = "Capture Source", 462 .info = conexant_mux_enum_info, 463 .get = conexant_mux_enum_get, 464 .put = conexant_mux_enum_put 465 }, 466 {} 467 }; 468 469 static const char * const slave_pfxs[] = { 470 "Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE", 471 NULL 472 }; 473 474 static int conexant_build_controls(struct hda_codec *codec) 475 { 476 struct conexant_spec *spec = codec->spec; 477 unsigned int i; 478 int err; 479 480 for (i = 0; i < spec->num_mixers; i++) { 481 err = snd_hda_add_new_ctls(codec, spec->mixers[i]); 482 if (err < 0) 483 return err; 484 } 485 if (spec->multiout.dig_out_nid) { 486 err = snd_hda_create_spdif_out_ctls(codec, 487 spec->multiout.dig_out_nid, 488 spec->multiout.dig_out_nid); 489 if (err < 0) 490 return err; 491 err = snd_hda_create_spdif_share_sw(codec, 492 &spec->multiout); 493 if (err < 0) 494 return err; 495 spec->multiout.share_spdif = 1; 496 } 497 if (spec->dig_in_nid) { 498 err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid); 499 if (err < 0) 500 return err; 501 } 502 503 /* if we have no master control, let's create it */ 504 if (spec->vmaster_nid && 505 !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { 506 unsigned int vmaster_tlv[4]; 507 snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, 508 HDA_OUTPUT, vmaster_tlv); 509 err = snd_hda_add_vmaster(codec, "Master Playback Volume", 510 vmaster_tlv, slave_pfxs, 511 "Playback Volume"); 512 if (err < 0) 513 return err; 514 } 515 if (spec->vmaster_nid && 516 !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { 517 err = snd_hda_add_vmaster(codec, "Master Playback Switch", 518 NULL, slave_pfxs, 519 "Playback Switch"); 520 if (err < 0) 521 return err; 522 } 523 524 if (spec->input_mux) { 525 err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); 526 if (err < 0) 527 return err; 528 } 529 530 err = add_beep_ctls(codec); 531 if (err < 0) 532 return err; 533 534 return 0; 535 } 536 537 static const struct hda_codec_ops conexant_patch_ops = { 538 .build_controls = conexant_build_controls, 539 .build_pcms = conexant_build_pcms, 540 .init = conexant_init, 541 .free = conexant_free, 542 .set_power_state = conexant_set_power, 543 }; 544 545 static int patch_conexant_auto(struct hda_codec *codec); 546 /* 547 * EAPD control 548 * the private value = nid | (invert << 8) 549 */ 550 551 #define cxt_eapd_info snd_ctl_boolean_mono_info 552 553 static int cxt_eapd_get(struct snd_kcontrol *kcontrol, 554 struct snd_ctl_elem_value *ucontrol) 555 { 556 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 557 struct conexant_spec *spec = codec->spec; 558 int invert = (kcontrol->private_value >> 8) & 1; 559 if (invert) 560 ucontrol->value.integer.value[0] = !spec->cur_eapd; 561 else 562 ucontrol->value.integer.value[0] = spec->cur_eapd; 563 return 0; 564 565 } 566 567 static int cxt_eapd_put(struct snd_kcontrol *kcontrol, 568 struct snd_ctl_elem_value *ucontrol) 569 { 570 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 571 struct conexant_spec *spec = codec->spec; 572 int invert = (kcontrol->private_value >> 8) & 1; 573 hda_nid_t nid = kcontrol->private_value & 0xff; 574 unsigned int eapd; 575 576 eapd = !!ucontrol->value.integer.value[0]; 577 if (invert) 578 eapd = !eapd; 579 if (eapd == spec->cur_eapd) 580 return 0; 581 582 spec->cur_eapd = eapd; 583 snd_hda_codec_write_cache(codec, nid, 584 0, AC_VERB_SET_EAPD_BTLENABLE, 585 eapd ? 0x02 : 0x00); 586 return 1; 587 } 588 589 /* controls for test mode */ 590 #ifdef CONFIG_SND_DEBUG 591 592 #define CXT_EAPD_SWITCH(xname, nid, mask) \ 593 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 594 .info = cxt_eapd_info, \ 595 .get = cxt_eapd_get, \ 596 .put = cxt_eapd_put, \ 597 .private_value = nid | (mask<<16) } 598 599 600 601 static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol, 602 struct snd_ctl_elem_info *uinfo) 603 { 604 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 605 struct conexant_spec *spec = codec->spec; 606 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, 607 spec->num_channel_mode); 608 } 609 610 static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol, 611 struct snd_ctl_elem_value *ucontrol) 612 { 613 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 614 struct conexant_spec *spec = codec->spec; 615 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, 616 spec->num_channel_mode, 617 spec->multiout.max_channels); 618 } 619 620 static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, 621 struct snd_ctl_elem_value *ucontrol) 622 { 623 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 624 struct conexant_spec *spec = codec->spec; 625 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, 626 spec->num_channel_mode, 627 &spec->multiout.max_channels); 628 return err; 629 } 630 631 #define CXT_PIN_MODE(xname, nid, dir) \ 632 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ 633 .info = conexant_ch_mode_info, \ 634 .get = conexant_ch_mode_get, \ 635 .put = conexant_ch_mode_put, \ 636 .private_value = nid | (dir<<16) } 637 638 #endif /* CONFIG_SND_DEBUG */ 639 640 /* Conexant 5045 specific */ 641 642 static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 }; 643 static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a }; 644 static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a }; 645 #define CXT5045_SPDIF_OUT 0x18 646 647 static const struct hda_channel_mode cxt5045_modes[1] = { 648 { 2, NULL }, 649 }; 650 651 static const struct hda_input_mux cxt5045_capture_source = { 652 .num_items = 2, 653 .items = { 654 { "Internal Mic", 0x1 }, 655 { "Mic", 0x2 }, 656 } 657 }; 658 659 static const struct hda_input_mux cxt5045_capture_source_benq = { 660 .num_items = 4, 661 .items = { 662 { "Internal Mic", 0x1 }, 663 { "Mic", 0x2 }, 664 { "Line", 0x3 }, 665 { "Mixer", 0x0 }, 666 } 667 }; 668 669 static const struct hda_input_mux cxt5045_capture_source_hp530 = { 670 .num_items = 2, 671 .items = { 672 { "Mic", 0x1 }, 673 { "Internal Mic", 0x2 }, 674 } 675 }; 676 677 /* turn on/off EAPD (+ mute HP) as a master switch */ 678 static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, 679 struct snd_ctl_elem_value *ucontrol) 680 { 681 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 682 struct conexant_spec *spec = codec->spec; 683 unsigned int bits; 684 685 if (!cxt_eapd_put(kcontrol, ucontrol)) 686 return 0; 687 688 /* toggle internal speakers mute depending of presence of 689 * the headphone jack 690 */ 691 bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; 692 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, 693 HDA_AMP_MUTE, bits); 694 695 bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; 696 snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0, 697 HDA_AMP_MUTE, bits); 698 return 1; 699 } 700 701 /* bind volumes of both NID 0x10 and 0x11 */ 702 static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = { 703 .ops = &snd_hda_bind_vol, 704 .values = { 705 HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), 706 HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT), 707 0 708 }, 709 }; 710 711 /* toggle input of built-in and mic jack appropriately */ 712 static void cxt5045_hp_automic(struct hda_codec *codec) 713 { 714 static const struct hda_verb mic_jack_on[] = { 715 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 716 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 717 {} 718 }; 719 static const struct hda_verb mic_jack_off[] = { 720 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 721 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 722 {} 723 }; 724 unsigned int present; 725 726 present = snd_hda_jack_detect(codec, 0x12); 727 if (present) 728 snd_hda_sequence_write(codec, mic_jack_on); 729 else 730 snd_hda_sequence_write(codec, mic_jack_off); 731 } 732 733 734 /* mute internal speaker if HP is plugged */ 735 static void cxt5045_hp_automute(struct hda_codec *codec) 736 { 737 struct conexant_spec *spec = codec->spec; 738 unsigned int bits; 739 740 spec->hp_present = snd_hda_jack_detect(codec, 0x11); 741 742 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 743 snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, 744 HDA_AMP_MUTE, bits); 745 } 746 747 /* unsolicited event for HP jack sensing */ 748 static void cxt5045_hp_unsol_event(struct hda_codec *codec, 749 unsigned int res) 750 { 751 res >>= 26; 752 switch (res) { 753 case CONEXANT_HP_EVENT: 754 cxt5045_hp_automute(codec); 755 break; 756 case CONEXANT_MIC_EVENT: 757 cxt5045_hp_automic(codec); 758 break; 759 760 } 761 } 762 763 static const struct snd_kcontrol_new cxt5045_mixers[] = { 764 HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), 765 HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), 766 HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), 767 HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), 768 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT), 769 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT), 770 HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT), 771 HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT), 772 HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), 773 { 774 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 775 .name = "Master Playback Switch", 776 .info = cxt_eapd_info, 777 .get = cxt_eapd_get, 778 .put = cxt5045_hp_master_sw_put, 779 .private_value = 0x10, 780 }, 781 782 {} 783 }; 784 785 static const struct snd_kcontrol_new cxt5045_benq_mixers[] = { 786 HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x3, HDA_INPUT), 787 HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x3, HDA_INPUT), 788 789 {} 790 }; 791 792 static const struct snd_kcontrol_new cxt5045_mixers_hp530[] = { 793 HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), 794 HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), 795 HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), 796 HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), 797 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x2, HDA_INPUT), 798 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x2, HDA_INPUT), 799 HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x1, HDA_INPUT), 800 HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x1, HDA_INPUT), 801 HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), 802 { 803 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 804 .name = "Master Playback Switch", 805 .info = cxt_eapd_info, 806 .get = cxt_eapd_get, 807 .put = cxt5045_hp_master_sw_put, 808 .private_value = 0x10, 809 }, 810 811 {} 812 }; 813 814 static const struct hda_verb cxt5045_init_verbs[] = { 815 /* Line in, Mic */ 816 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, 817 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, 818 /* HP, Amp */ 819 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 820 {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, 821 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 822 {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, 823 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 824 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 825 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 826 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 827 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 828 /* Record selector: Internal mic */ 829 {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, 830 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 831 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, 832 /* SPDIF route: PCM */ 833 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 834 { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, 835 /* EAPD */ 836 {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ 837 { } /* end */ 838 }; 839 840 static const struct hda_verb cxt5045_benq_init_verbs[] = { 841 /* Internal Mic, Mic */ 842 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, 843 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, 844 /* Line In,HP, Amp */ 845 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 846 {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, 847 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 848 {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, 849 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 850 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 851 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 852 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 853 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 854 /* Record selector: Internal mic */ 855 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1}, 856 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 857 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, 858 /* SPDIF route: PCM */ 859 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 860 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, 861 /* EAPD */ 862 {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 863 { } /* end */ 864 }; 865 866 static const struct hda_verb cxt5045_hp_sense_init_verbs[] = { 867 /* pin sensing on HP jack */ 868 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 869 { } /* end */ 870 }; 871 872 static const struct hda_verb cxt5045_mic_sense_init_verbs[] = { 873 /* pin sensing on HP jack */ 874 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 875 { } /* end */ 876 }; 877 878 #ifdef CONFIG_SND_DEBUG 879 /* Test configuration for debugging, modelled after the ALC260 test 880 * configuration. 881 */ 882 static const struct hda_input_mux cxt5045_test_capture_source = { 883 .num_items = 5, 884 .items = { 885 { "MIXER", 0x0 }, 886 { "MIC1 pin", 0x1 }, 887 { "LINE1 pin", 0x2 }, 888 { "HP-OUT pin", 0x3 }, 889 { "CD pin", 0x4 }, 890 }, 891 }; 892 893 static const struct snd_kcontrol_new cxt5045_test_mixer[] = { 894 895 /* Output controls */ 896 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), 897 HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), 898 HDA_CODEC_VOLUME("HP-OUT Playback Volume", 0x11, 0x0, HDA_OUTPUT), 899 HDA_CODEC_MUTE("HP-OUT Playback Switch", 0x11, 0x0, HDA_OUTPUT), 900 HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x12, 0x0, HDA_OUTPUT), 901 HDA_CODEC_MUTE("LINE1 Playback Switch", 0x12, 0x0, HDA_OUTPUT), 902 903 /* Modes for retasking pin widgets */ 904 CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), 905 CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT), 906 907 /* EAPD Switch Control */ 908 CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), 909 910 /* Loopback mixer controls */ 911 912 HDA_CODEC_VOLUME("PCM Volume", 0x17, 0x0, HDA_INPUT), 913 HDA_CODEC_MUTE("PCM Switch", 0x17, 0x0, HDA_INPUT), 914 HDA_CODEC_VOLUME("MIC1 pin Volume", 0x17, 0x1, HDA_INPUT), 915 HDA_CODEC_MUTE("MIC1 pin Switch", 0x17, 0x1, HDA_INPUT), 916 HDA_CODEC_VOLUME("LINE1 pin Volume", 0x17, 0x2, HDA_INPUT), 917 HDA_CODEC_MUTE("LINE1 pin Switch", 0x17, 0x2, HDA_INPUT), 918 HDA_CODEC_VOLUME("HP-OUT pin Volume", 0x17, 0x3, HDA_INPUT), 919 HDA_CODEC_MUTE("HP-OUT pin Switch", 0x17, 0x3, HDA_INPUT), 920 HDA_CODEC_VOLUME("CD pin Volume", 0x17, 0x4, HDA_INPUT), 921 HDA_CODEC_MUTE("CD pin Switch", 0x17, 0x4, HDA_INPUT), 922 { 923 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 924 .name = "Input Source", 925 .info = conexant_mux_enum_info, 926 .get = conexant_mux_enum_get, 927 .put = conexant_mux_enum_put, 928 }, 929 /* Audio input controls */ 930 HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), 931 HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), 932 { } /* end */ 933 }; 934 935 static const struct hda_verb cxt5045_test_init_verbs[] = { 936 /* Set connections */ 937 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, 938 { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, 939 { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, 940 /* Enable retasking pins as output, initially without power amp */ 941 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 942 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 943 944 /* Disable digital (SPDIF) pins initially, but users can enable 945 * them via a mixer switch. In the case of SPDIF-out, this initverb 946 * payload also sets the generation to 0, output to be in "consumer" 947 * PCM format, copyright asserted, no pre-emphasis and no validity 948 * control. 949 */ 950 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 951 {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, 952 953 /* Unmute retasking pin widget output buffers since the default 954 * state appears to be output. As the pin mode is changed by the 955 * user the pin mode control will take care of enabling the pin's 956 * input/output buffers as needed. 957 */ 958 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 959 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 960 961 /* Mute capture amp left and right */ 962 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 963 964 /* Set ADC connection select to match default mixer setting (mic1 965 * pin) 966 */ 967 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, 968 {0x17, AC_VERB_SET_CONNECT_SEL, 0x01}, 969 970 /* Mute all inputs to mixer widget (even unconnected ones) */ 971 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer */ 972 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */ 973 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */ 974 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */ 975 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 976 977 { } 978 }; 979 #endif 980 981 982 /* initialize jack-sensing, too */ 983 static int cxt5045_init(struct hda_codec *codec) 984 { 985 conexant_init(codec); 986 cxt5045_hp_automute(codec); 987 return 0; 988 } 989 990 991 enum { 992 CXT5045_LAPTOP_HPSENSE, 993 CXT5045_LAPTOP_MICSENSE, 994 CXT5045_LAPTOP_HPMICSENSE, 995 CXT5045_BENQ, 996 CXT5045_LAPTOP_HP530, 997 #ifdef CONFIG_SND_DEBUG 998 CXT5045_TEST, 999 #endif 1000 CXT5045_AUTO, 1001 CXT5045_MODELS 1002 }; 1003 1004 static const char * const cxt5045_models[CXT5045_MODELS] = { 1005 [CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense", 1006 [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense", 1007 [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense", 1008 [CXT5045_BENQ] = "benq", 1009 [CXT5045_LAPTOP_HP530] = "laptop-hp530", 1010 #ifdef CONFIG_SND_DEBUG 1011 [CXT5045_TEST] = "test", 1012 #endif 1013 [CXT5045_AUTO] = "auto", 1014 }; 1015 1016 static const struct snd_pci_quirk cxt5045_cfg_tbl[] = { 1017 SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), 1018 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), 1019 SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), 1020 SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), 1021 SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE), 1022 SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", 1023 CXT5045_LAPTOP_HPMICSENSE), 1024 SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), 1025 SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), 1026 SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), 1027 SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", 1028 CXT5045_LAPTOP_HPMICSENSE), 1029 SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), 1030 {} 1031 }; 1032 1033 static int patch_cxt5045(struct hda_codec *codec) 1034 { 1035 struct conexant_spec *spec; 1036 int board_config; 1037 1038 board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, 1039 cxt5045_models, 1040 cxt5045_cfg_tbl); 1041 if (board_config < 0) 1042 board_config = CXT5045_AUTO; /* model=auto as default */ 1043 if (board_config == CXT5045_AUTO) 1044 return patch_conexant_auto(codec); 1045 1046 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1047 if (!spec) 1048 return -ENOMEM; 1049 codec->spec = spec; 1050 codec->single_adc_amp = 1; 1051 1052 spec->multiout.max_channels = 2; 1053 spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); 1054 spec->multiout.dac_nids = cxt5045_dac_nids; 1055 spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT; 1056 spec->num_adc_nids = 1; 1057 spec->adc_nids = cxt5045_adc_nids; 1058 spec->capsrc_nids = cxt5045_capsrc_nids; 1059 spec->input_mux = &cxt5045_capture_source; 1060 spec->num_mixers = 1; 1061 spec->mixers[0] = cxt5045_mixers; 1062 spec->num_init_verbs = 1; 1063 spec->init_verbs[0] = cxt5045_init_verbs; 1064 spec->spdif_route = 0; 1065 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes); 1066 spec->channel_mode = cxt5045_modes; 1067 1068 set_beep_amp(spec, 0x16, 0, 1); 1069 1070 codec->patch_ops = conexant_patch_ops; 1071 1072 switch (board_config) { 1073 case CXT5045_LAPTOP_HPSENSE: 1074 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; 1075 spec->input_mux = &cxt5045_capture_source; 1076 spec->num_init_verbs = 2; 1077 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; 1078 spec->mixers[0] = cxt5045_mixers; 1079 codec->patch_ops.init = cxt5045_init; 1080 break; 1081 case CXT5045_LAPTOP_MICSENSE: 1082 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; 1083 spec->input_mux = &cxt5045_capture_source; 1084 spec->num_init_verbs = 2; 1085 spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; 1086 spec->mixers[0] = cxt5045_mixers; 1087 codec->patch_ops.init = cxt5045_init; 1088 break; 1089 default: 1090 case CXT5045_LAPTOP_HPMICSENSE: 1091 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; 1092 spec->input_mux = &cxt5045_capture_source; 1093 spec->num_init_verbs = 3; 1094 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; 1095 spec->init_verbs[2] = cxt5045_mic_sense_init_verbs; 1096 spec->mixers[0] = cxt5045_mixers; 1097 codec->patch_ops.init = cxt5045_init; 1098 break; 1099 case CXT5045_BENQ: 1100 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; 1101 spec->input_mux = &cxt5045_capture_source_benq; 1102 spec->num_init_verbs = 1; 1103 spec->init_verbs[0] = cxt5045_benq_init_verbs; 1104 spec->mixers[0] = cxt5045_mixers; 1105 spec->mixers[1] = cxt5045_benq_mixers; 1106 spec->num_mixers = 2; 1107 codec->patch_ops.init = cxt5045_init; 1108 break; 1109 case CXT5045_LAPTOP_HP530: 1110 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; 1111 spec->input_mux = &cxt5045_capture_source_hp530; 1112 spec->num_init_verbs = 2; 1113 spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; 1114 spec->mixers[0] = cxt5045_mixers_hp530; 1115 codec->patch_ops.init = cxt5045_init; 1116 break; 1117 #ifdef CONFIG_SND_DEBUG 1118 case CXT5045_TEST: 1119 spec->input_mux = &cxt5045_test_capture_source; 1120 spec->mixers[0] = cxt5045_test_mixer; 1121 spec->init_verbs[0] = cxt5045_test_init_verbs; 1122 break; 1123 1124 #endif 1125 } 1126 1127 switch (codec->subsystem_id >> 16) { 1128 case 0x103c: 1129 case 0x1631: 1130 case 0x1734: 1131 case 0x17aa: 1132 /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have 1133 * really bad sound over 0dB on NID 0x17. Fix max PCM level to 1134 * 0 dB (originally it has 0x2b steps with 0dB offset 0x14) 1135 */ 1136 snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, 1137 (0x14 << AC_AMPCAP_OFFSET_SHIFT) | 1138 (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) | 1139 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 1140 (1 << AC_AMPCAP_MUTE_SHIFT)); 1141 break; 1142 } 1143 1144 if (spec->beep_amp) 1145 snd_hda_attach_beep_device(codec, spec->beep_amp); 1146 1147 return 0; 1148 } 1149 1150 1151 /* Conexant 5047 specific */ 1152 #define CXT5047_SPDIF_OUT 0x11 1153 1154 static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ 1155 static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; 1156 static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; 1157 1158 static const struct hda_channel_mode cxt5047_modes[1] = { 1159 { 2, NULL }, 1160 }; 1161 1162 static const struct hda_input_mux cxt5047_toshiba_capture_source = { 1163 .num_items = 2, 1164 .items = { 1165 { "ExtMic", 0x2 }, 1166 { "Line-In", 0x1 }, 1167 } 1168 }; 1169 1170 /* turn on/off EAPD (+ mute HP) as a master switch */ 1171 static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, 1172 struct snd_ctl_elem_value *ucontrol) 1173 { 1174 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1175 struct conexant_spec *spec = codec->spec; 1176 unsigned int bits; 1177 1178 if (!cxt_eapd_put(kcontrol, ucontrol)) 1179 return 0; 1180 1181 /* toggle internal speakers mute depending of presence of 1182 * the headphone jack 1183 */ 1184 bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; 1185 /* NOTE: Conexat codec needs the index for *OUTPUT* amp of 1186 * pin widgets unlike other codecs. In this case, we need to 1187 * set index 0x01 for the volume from the mixer amp 0x19. 1188 */ 1189 snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, 1190 HDA_AMP_MUTE, bits); 1191 bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; 1192 snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, 1193 HDA_AMP_MUTE, bits); 1194 return 1; 1195 } 1196 1197 /* mute internal speaker if HP is plugged */ 1198 static void cxt5047_hp_automute(struct hda_codec *codec) 1199 { 1200 struct conexant_spec *spec = codec->spec; 1201 unsigned int bits; 1202 1203 spec->hp_present = snd_hda_jack_detect(codec, 0x13); 1204 1205 bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 1206 /* See the note in cxt5047_hp_master_sw_put */ 1207 snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, 1208 HDA_AMP_MUTE, bits); 1209 } 1210 1211 /* toggle input of built-in and mic jack appropriately */ 1212 static void cxt5047_hp_automic(struct hda_codec *codec) 1213 { 1214 static const struct hda_verb mic_jack_on[] = { 1215 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1216 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1217 {} 1218 }; 1219 static const struct hda_verb mic_jack_off[] = { 1220 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1221 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1222 {} 1223 }; 1224 unsigned int present; 1225 1226 present = snd_hda_jack_detect(codec, 0x15); 1227 if (present) 1228 snd_hda_sequence_write(codec, mic_jack_on); 1229 else 1230 snd_hda_sequence_write(codec, mic_jack_off); 1231 } 1232 1233 /* unsolicited event for HP jack sensing */ 1234 static void cxt5047_hp_unsol_event(struct hda_codec *codec, 1235 unsigned int res) 1236 { 1237 switch (res >> 26) { 1238 case CONEXANT_HP_EVENT: 1239 cxt5047_hp_automute(codec); 1240 break; 1241 case CONEXANT_MIC_EVENT: 1242 cxt5047_hp_automic(codec); 1243 break; 1244 } 1245 } 1246 1247 static const struct snd_kcontrol_new cxt5047_base_mixers[] = { 1248 HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), 1249 HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), 1250 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), 1251 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), 1252 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), 1253 HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), 1254 HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), 1255 { 1256 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1257 .name = "Master Playback Switch", 1258 .info = cxt_eapd_info, 1259 .get = cxt_eapd_get, 1260 .put = cxt5047_hp_master_sw_put, 1261 .private_value = 0x13, 1262 }, 1263 1264 {} 1265 }; 1266 1267 static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { 1268 /* See the note in cxt5047_hp_master_sw_put */ 1269 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), 1270 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), 1271 {} 1272 }; 1273 1274 static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { 1275 HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), 1276 { } /* end */ 1277 }; 1278 1279 static const struct hda_verb cxt5047_init_verbs[] = { 1280 /* Line in, Mic, Built-in Mic */ 1281 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 1282 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, 1283 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, 1284 /* HP, Speaker */ 1285 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, 1286 {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ 1287 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ 1288 /* Record selector: Mic */ 1289 {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, 1290 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 1291 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, 1292 {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, 1293 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, 1294 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, 1295 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, 1296 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, 1297 /* SPDIF route: PCM */ 1298 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, 1299 /* Enable unsolicited events */ 1300 {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 1301 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 1302 { } /* end */ 1303 }; 1304 1305 /* configuration for Toshiba Laptops */ 1306 static const struct hda_verb cxt5047_toshiba_init_verbs[] = { 1307 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ 1308 {} 1309 }; 1310 1311 /* Test configuration for debugging, modelled after the ALC260 test 1312 * configuration. 1313 */ 1314 #ifdef CONFIG_SND_DEBUG 1315 static const struct hda_input_mux cxt5047_test_capture_source = { 1316 .num_items = 4, 1317 .items = { 1318 { "LINE1 pin", 0x0 }, 1319 { "MIC1 pin", 0x1 }, 1320 { "MIC2 pin", 0x2 }, 1321 { "CD pin", 0x3 }, 1322 }, 1323 }; 1324 1325 static const struct snd_kcontrol_new cxt5047_test_mixer[] = { 1326 1327 /* Output only controls */ 1328 HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT), 1329 HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT), 1330 HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT), 1331 HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT), 1332 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT), 1333 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT), 1334 HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT), 1335 HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT), 1336 HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT), 1337 HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT), 1338 HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT), 1339 HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT), 1340 1341 /* Modes for retasking pin widgets */ 1342 CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT), 1343 CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT), 1344 1345 /* EAPD Switch Control */ 1346 CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0), 1347 1348 /* Loopback mixer controls */ 1349 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT), 1350 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT), 1351 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT), 1352 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT), 1353 HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT), 1354 HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT), 1355 HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT), 1356 HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT), 1357 1358 HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT), 1359 HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT), 1360 HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT), 1361 HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT), 1362 HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT), 1363 HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT), 1364 HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT), 1365 HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT), 1366 { 1367 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1368 .name = "Input Source", 1369 .info = conexant_mux_enum_info, 1370 .get = conexant_mux_enum_get, 1371 .put = conexant_mux_enum_put, 1372 }, 1373 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), 1374 1375 { } /* end */ 1376 }; 1377 1378 static const struct hda_verb cxt5047_test_init_verbs[] = { 1379 /* Enable retasking pins as output, initially without power amp */ 1380 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1381 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1382 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1383 1384 /* Disable digital (SPDIF) pins initially, but users can enable 1385 * them via a mixer switch. In the case of SPDIF-out, this initverb 1386 * payload also sets the generation to 0, output to be in "consumer" 1387 * PCM format, copyright asserted, no pre-emphasis and no validity 1388 * control. 1389 */ 1390 {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, 1391 1392 /* Ensure mic1, mic2, line1 pin widgets take input from the 1393 * OUT1 sum bus when acting as an output. 1394 */ 1395 {0x1a, AC_VERB_SET_CONNECT_SEL, 0}, 1396 {0x1b, AC_VERB_SET_CONNECT_SEL, 0}, 1397 1398 /* Start with output sum widgets muted and their output gains at min */ 1399 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1400 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 1401 1402 /* Unmute retasking pin widget output buffers since the default 1403 * state appears to be output. As the pin mode is changed by the 1404 * user the pin mode control will take care of enabling the pin's 1405 * input/output buffers as needed. 1406 */ 1407 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1408 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1409 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1410 1411 /* Mute capture amp left and right */ 1412 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 1413 1414 /* Set ADC connection select to match default mixer setting (mic1 1415 * pin) 1416 */ 1417 {0x12, AC_VERB_SET_CONNECT_SEL, 0x00}, 1418 1419 /* Mute all inputs to mixer widget (even unconnected ones) */ 1420 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ 1421 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ 1422 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ 1423 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ 1424 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ 1425 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ 1426 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ 1427 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ 1428 1429 { } 1430 }; 1431 #endif 1432 1433 1434 /* initialize jack-sensing, too */ 1435 static int cxt5047_hp_init(struct hda_codec *codec) 1436 { 1437 conexant_init(codec); 1438 cxt5047_hp_automute(codec); 1439 return 0; 1440 } 1441 1442 1443 enum { 1444 CXT5047_LAPTOP, /* Laptops w/o EAPD support */ 1445 CXT5047_LAPTOP_HP, /* Some HP laptops */ 1446 CXT5047_LAPTOP_EAPD, /* Laptops with EAPD support */ 1447 #ifdef CONFIG_SND_DEBUG 1448 CXT5047_TEST, 1449 #endif 1450 CXT5047_AUTO, 1451 CXT5047_MODELS 1452 }; 1453 1454 static const char * const cxt5047_models[CXT5047_MODELS] = { 1455 [CXT5047_LAPTOP] = "laptop", 1456 [CXT5047_LAPTOP_HP] = "laptop-hp", 1457 [CXT5047_LAPTOP_EAPD] = "laptop-eapd", 1458 #ifdef CONFIG_SND_DEBUG 1459 [CXT5047_TEST] = "test", 1460 #endif 1461 [CXT5047_AUTO] = "auto", 1462 }; 1463 1464 static const struct snd_pci_quirk cxt5047_cfg_tbl[] = { 1465 SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), 1466 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", 1467 CXT5047_LAPTOP), 1468 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), 1469 {} 1470 }; 1471 1472 static int patch_cxt5047(struct hda_codec *codec) 1473 { 1474 struct conexant_spec *spec; 1475 int board_config; 1476 1477 board_config = snd_hda_check_board_config(codec, CXT5047_MODELS, 1478 cxt5047_models, 1479 cxt5047_cfg_tbl); 1480 if (board_config < 0) 1481 board_config = CXT5047_AUTO; /* model=auto as default */ 1482 if (board_config == CXT5047_AUTO) 1483 return patch_conexant_auto(codec); 1484 1485 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1486 if (!spec) 1487 return -ENOMEM; 1488 codec->spec = spec; 1489 codec->pin_amp_workaround = 1; 1490 1491 spec->multiout.max_channels = 2; 1492 spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); 1493 spec->multiout.dac_nids = cxt5047_dac_nids; 1494 spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT; 1495 spec->num_adc_nids = 1; 1496 spec->adc_nids = cxt5047_adc_nids; 1497 spec->capsrc_nids = cxt5047_capsrc_nids; 1498 spec->num_mixers = 1; 1499 spec->mixers[0] = cxt5047_base_mixers; 1500 spec->num_init_verbs = 1; 1501 spec->init_verbs[0] = cxt5047_init_verbs; 1502 spec->spdif_route = 0; 1503 spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes), 1504 spec->channel_mode = cxt5047_modes, 1505 1506 codec->patch_ops = conexant_patch_ops; 1507 1508 switch (board_config) { 1509 case CXT5047_LAPTOP: 1510 spec->num_mixers = 2; 1511 spec->mixers[1] = cxt5047_hp_spk_mixers; 1512 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; 1513 break; 1514 case CXT5047_LAPTOP_HP: 1515 spec->num_mixers = 2; 1516 spec->mixers[1] = cxt5047_hp_only_mixers; 1517 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; 1518 codec->patch_ops.init = cxt5047_hp_init; 1519 break; 1520 case CXT5047_LAPTOP_EAPD: 1521 spec->input_mux = &cxt5047_toshiba_capture_source; 1522 spec->num_mixers = 2; 1523 spec->mixers[1] = cxt5047_hp_spk_mixers; 1524 spec->num_init_verbs = 2; 1525 spec->init_verbs[1] = cxt5047_toshiba_init_verbs; 1526 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; 1527 break; 1528 #ifdef CONFIG_SND_DEBUG 1529 case CXT5047_TEST: 1530 spec->input_mux = &cxt5047_test_capture_source; 1531 spec->mixers[0] = cxt5047_test_mixer; 1532 spec->init_verbs[0] = cxt5047_test_init_verbs; 1533 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; 1534 #endif 1535 } 1536 spec->vmaster_nid = 0x13; 1537 1538 switch (codec->subsystem_id >> 16) { 1539 case 0x103c: 1540 /* HP laptops have really bad sound over 0 dB on NID 0x10. 1541 * Fix max PCM level to 0 dB (originally it has 0x1e steps 1542 * with 0 dB offset 0x17) 1543 */ 1544 snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT, 1545 (0x17 << AC_AMPCAP_OFFSET_SHIFT) | 1546 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 1547 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | 1548 (1 << AC_AMPCAP_MUTE_SHIFT)); 1549 break; 1550 } 1551 1552 return 0; 1553 } 1554 1555 /* Conexant 5051 specific */ 1556 static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; 1557 static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; 1558 1559 static const struct hda_channel_mode cxt5051_modes[1] = { 1560 { 2, NULL }, 1561 }; 1562 1563 static void cxt5051_update_speaker(struct hda_codec *codec) 1564 { 1565 struct conexant_spec *spec = codec->spec; 1566 unsigned int pinctl; 1567 /* headphone pin */ 1568 pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; 1569 snd_hda_set_pin_ctl(codec, 0x16, pinctl); 1570 /* speaker pin */ 1571 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; 1572 snd_hda_set_pin_ctl(codec, 0x1a, pinctl); 1573 /* on ideapad there is an additional speaker (subwoofer) to mute */ 1574 if (spec->ideapad) 1575 snd_hda_set_pin_ctl(codec, 0x1b, pinctl); 1576 } 1577 1578 /* turn on/off EAPD (+ mute HP) as a master switch */ 1579 static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol, 1580 struct snd_ctl_elem_value *ucontrol) 1581 { 1582 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1583 1584 if (!cxt_eapd_put(kcontrol, ucontrol)) 1585 return 0; 1586 cxt5051_update_speaker(codec); 1587 return 1; 1588 } 1589 1590 /* toggle input of built-in and mic jack appropriately */ 1591 static void cxt5051_portb_automic(struct hda_codec *codec) 1592 { 1593 struct conexant_spec *spec = codec->spec; 1594 unsigned int present; 1595 1596 if (!(spec->auto_mic & AUTO_MIC_PORTB)) 1597 return; 1598 present = snd_hda_jack_detect(codec, 0x17); 1599 snd_hda_codec_write(codec, 0x14, 0, 1600 AC_VERB_SET_CONNECT_SEL, 1601 present ? 0x01 : 0x00); 1602 } 1603 1604 /* switch the current ADC according to the jack state */ 1605 static void cxt5051_portc_automic(struct hda_codec *codec) 1606 { 1607 struct conexant_spec *spec = codec->spec; 1608 unsigned int present; 1609 hda_nid_t new_adc; 1610 1611 if (!(spec->auto_mic & AUTO_MIC_PORTC)) 1612 return; 1613 present = snd_hda_jack_detect(codec, 0x18); 1614 if (present) 1615 spec->cur_adc_idx = 1; 1616 else 1617 spec->cur_adc_idx = 0; 1618 new_adc = spec->adc_nids[spec->cur_adc_idx]; 1619 if (spec->cur_adc && spec->cur_adc != new_adc) { 1620 /* stream is running, let's swap the current ADC */ 1621 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); 1622 spec->cur_adc = new_adc; 1623 snd_hda_codec_setup_stream(codec, new_adc, 1624 spec->cur_adc_stream_tag, 0, 1625 spec->cur_adc_format); 1626 } 1627 } 1628 1629 /* mute internal speaker if HP is plugged */ 1630 static void cxt5051_hp_automute(struct hda_codec *codec) 1631 { 1632 struct conexant_spec *spec = codec->spec; 1633 1634 spec->hp_present = snd_hda_jack_detect(codec, 0x16); 1635 cxt5051_update_speaker(codec); 1636 } 1637 1638 /* unsolicited event for HP jack sensing */ 1639 static void cxt5051_hp_unsol_event(struct hda_codec *codec, 1640 unsigned int res) 1641 { 1642 switch (res >> 26) { 1643 case CONEXANT_HP_EVENT: 1644 cxt5051_hp_automute(codec); 1645 break; 1646 case CXT5051_PORTB_EVENT: 1647 cxt5051_portb_automic(codec); 1648 break; 1649 case CXT5051_PORTC_EVENT: 1650 cxt5051_portc_automic(codec); 1651 break; 1652 } 1653 } 1654 1655 static const struct snd_kcontrol_new cxt5051_playback_mixers[] = { 1656 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), 1657 { 1658 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1659 .name = "Master Playback Switch", 1660 .info = cxt_eapd_info, 1661 .get = cxt_eapd_get, 1662 .put = cxt5051_hp_master_sw_put, 1663 .private_value = 0x1a, 1664 }, 1665 {} 1666 }; 1667 1668 static const struct snd_kcontrol_new cxt5051_capture_mixers[] = { 1669 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), 1670 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), 1671 HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), 1672 HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), 1673 HDA_CODEC_VOLUME("Dock Mic Volume", 0x15, 0x00, HDA_INPUT), 1674 HDA_CODEC_MUTE("Dock Mic Switch", 0x15, 0x00, HDA_INPUT), 1675 {} 1676 }; 1677 1678 static const struct snd_kcontrol_new cxt5051_hp_mixers[] = { 1679 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), 1680 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), 1681 HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT), 1682 HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT), 1683 {} 1684 }; 1685 1686 static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { 1687 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT), 1688 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT), 1689 {} 1690 }; 1691 1692 static const struct snd_kcontrol_new cxt5051_f700_mixers[] = { 1693 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT), 1694 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT), 1695 {} 1696 }; 1697 1698 static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { 1699 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), 1700 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), 1701 HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), 1702 HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), 1703 {} 1704 }; 1705 1706 static const struct hda_verb cxt5051_init_verbs[] = { 1707 /* Line in, Mic */ 1708 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1709 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1710 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1711 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1712 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1713 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1714 /* SPK */ 1715 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1716 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, 1717 /* HP, Amp */ 1718 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1719 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, 1720 /* DAC1 */ 1721 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1722 /* Record selector: Internal mic */ 1723 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, 1724 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1725 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, 1726 /* SPDIF route: PCM */ 1727 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1728 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, 1729 /* EAPD */ 1730 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 1731 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, 1732 { } /* end */ 1733 }; 1734 1735 static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { 1736 /* Line in, Mic */ 1737 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1738 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1739 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, 1740 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, 1741 /* SPK */ 1742 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1743 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, 1744 /* HP, Amp */ 1745 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1746 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, 1747 /* DAC1 */ 1748 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1749 /* Record selector: Internal mic */ 1750 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1751 {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, 1752 /* SPDIF route: PCM */ 1753 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, 1754 /* EAPD */ 1755 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 1756 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, 1757 { } /* end */ 1758 }; 1759 1760 static const struct hda_verb cxt5051_f700_init_verbs[] = { 1761 /* Line in, Mic */ 1762 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1763 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1764 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, 1765 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, 1766 /* SPK */ 1767 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1768 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, 1769 /* HP, Amp */ 1770 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1771 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, 1772 /* DAC1 */ 1773 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1774 /* Record selector: Internal mic */ 1775 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1776 {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, 1777 /* SPDIF route: PCM */ 1778 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, 1779 /* EAPD */ 1780 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 1781 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, 1782 { } /* end */ 1783 }; 1784 1785 static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, 1786 unsigned int event) 1787 { 1788 snd_hda_codec_write(codec, nid, 0, 1789 AC_VERB_SET_UNSOLICITED_ENABLE, 1790 AC_USRSP_EN | event); 1791 } 1792 1793 static const struct hda_verb cxt5051_ideapad_init_verbs[] = { 1794 /* Subwoofer */ 1795 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1796 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 1797 { } /* end */ 1798 }; 1799 1800 /* initialize jack-sensing, too */ 1801 static int cxt5051_init(struct hda_codec *codec) 1802 { 1803 struct conexant_spec *spec = codec->spec; 1804 1805 conexant_init(codec); 1806 1807 if (spec->auto_mic & AUTO_MIC_PORTB) 1808 cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT); 1809 if (spec->auto_mic & AUTO_MIC_PORTC) 1810 cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT); 1811 1812 if (codec->patch_ops.unsol_event) { 1813 cxt5051_hp_automute(codec); 1814 cxt5051_portb_automic(codec); 1815 cxt5051_portc_automic(codec); 1816 } 1817 return 0; 1818 } 1819 1820 1821 enum { 1822 CXT5051_LAPTOP, /* Laptops w/ EAPD support */ 1823 CXT5051_HP, /* no docking */ 1824 CXT5051_HP_DV6736, /* HP without mic switch */ 1825 CXT5051_F700, /* HP Compaq Presario F700 */ 1826 CXT5051_TOSHIBA, /* Toshiba M300 & co */ 1827 CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */ 1828 CXT5051_AUTO, /* auto-parser */ 1829 CXT5051_MODELS 1830 }; 1831 1832 static const char *const cxt5051_models[CXT5051_MODELS] = { 1833 [CXT5051_LAPTOP] = "laptop", 1834 [CXT5051_HP] = "hp", 1835 [CXT5051_HP_DV6736] = "hp-dv6736", 1836 [CXT5051_F700] = "hp-700", 1837 [CXT5051_TOSHIBA] = "toshiba", 1838 [CXT5051_IDEAPAD] = "ideapad", 1839 [CXT5051_AUTO] = "auto", 1840 }; 1841 1842 static const struct snd_pci_quirk cxt5051_cfg_tbl[] = { 1843 SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), 1844 SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), 1845 SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700), 1846 SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA), 1847 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", 1848 CXT5051_LAPTOP), 1849 SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), 1850 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD), 1851 {} 1852 }; 1853 1854 static int patch_cxt5051(struct hda_codec *codec) 1855 { 1856 struct conexant_spec *spec; 1857 int board_config; 1858 1859 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, 1860 cxt5051_models, 1861 cxt5051_cfg_tbl); 1862 if (board_config < 0) 1863 board_config = CXT5051_AUTO; /* model=auto as default */ 1864 if (board_config == CXT5051_AUTO) 1865 return patch_conexant_auto(codec); 1866 1867 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1868 if (!spec) 1869 return -ENOMEM; 1870 codec->spec = spec; 1871 codec->pin_amp_workaround = 1; 1872 1873 codec->patch_ops = conexant_patch_ops; 1874 codec->patch_ops.init = cxt5051_init; 1875 1876 spec->multiout.max_channels = 2; 1877 spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids); 1878 spec->multiout.dac_nids = cxt5051_dac_nids; 1879 spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT; 1880 spec->num_adc_nids = 1; /* not 2; via auto-mic switch */ 1881 spec->adc_nids = cxt5051_adc_nids; 1882 spec->num_mixers = 2; 1883 spec->mixers[0] = cxt5051_capture_mixers; 1884 spec->mixers[1] = cxt5051_playback_mixers; 1885 spec->num_init_verbs = 1; 1886 spec->init_verbs[0] = cxt5051_init_verbs; 1887 spec->spdif_route = 0; 1888 spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes); 1889 spec->channel_mode = cxt5051_modes; 1890 spec->cur_adc = 0; 1891 spec->cur_adc_idx = 0; 1892 1893 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); 1894 1895 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; 1896 1897 spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC; 1898 switch (board_config) { 1899 case CXT5051_HP: 1900 spec->mixers[0] = cxt5051_hp_mixers; 1901 break; 1902 case CXT5051_HP_DV6736: 1903 spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; 1904 spec->mixers[0] = cxt5051_hp_dv6736_mixers; 1905 spec->auto_mic = 0; 1906 break; 1907 case CXT5051_F700: 1908 spec->init_verbs[0] = cxt5051_f700_init_verbs; 1909 spec->mixers[0] = cxt5051_f700_mixers; 1910 spec->auto_mic = 0; 1911 break; 1912 case CXT5051_TOSHIBA: 1913 spec->mixers[0] = cxt5051_toshiba_mixers; 1914 spec->auto_mic = AUTO_MIC_PORTB; 1915 break; 1916 case CXT5051_IDEAPAD: 1917 spec->init_verbs[spec->num_init_verbs++] = 1918 cxt5051_ideapad_init_verbs; 1919 spec->ideapad = 1; 1920 break; 1921 } 1922 1923 if (spec->beep_amp) 1924 snd_hda_attach_beep_device(codec, spec->beep_amp); 1925 1926 return 0; 1927 } 1928 1929 /* Conexant 5066 specific */ 1930 1931 static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 }; 1932 static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; 1933 static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; 1934 static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 }; 1935 1936 /* OLPC's microphone port is DC coupled for use with external sensors, 1937 * therefore we use a 50% mic bias in order to center the input signal with 1938 * the DC input range of the codec. */ 1939 #define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50 1940 1941 static const struct hda_channel_mode cxt5066_modes[1] = { 1942 { 2, NULL }, 1943 }; 1944 1945 #define HP_PRESENT_PORT_A (1 << 0) 1946 #define HP_PRESENT_PORT_D (1 << 1) 1947 #define hp_port_a_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_A) 1948 #define hp_port_d_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_D) 1949 1950 static void cxt5066_update_speaker(struct hda_codec *codec) 1951 { 1952 struct conexant_spec *spec = codec->spec; 1953 unsigned int pinctl; 1954 1955 snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n", 1956 spec->hp_present, spec->cur_eapd); 1957 1958 /* Port A (HP) */ 1959 pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; 1960 snd_hda_set_pin_ctl(codec, 0x19, pinctl); 1961 1962 /* Port D (HP/LO) */ 1963 pinctl = spec->cur_eapd ? spec->port_d_mode : 0; 1964 if (spec->dell_automute || spec->thinkpad) { 1965 /* Mute if Port A is connected */ 1966 if (hp_port_a_present(spec)) 1967 pinctl = 0; 1968 } else { 1969 /* Thinkpad/Dell doesn't give pin-D status */ 1970 if (!hp_port_d_present(spec)) 1971 pinctl = 0; 1972 } 1973 snd_hda_set_pin_ctl(codec, 0x1c, pinctl); 1974 1975 /* CLASS_D AMP */ 1976 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; 1977 snd_hda_set_pin_ctl(codec, 0x1f, pinctl); 1978 } 1979 1980 /* turn on/off EAPD (+ mute HP) as a master switch */ 1981 static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol, 1982 struct snd_ctl_elem_value *ucontrol) 1983 { 1984 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1985 1986 if (!cxt_eapd_put(kcontrol, ucontrol)) 1987 return 0; 1988 1989 cxt5066_update_speaker(codec); 1990 return 1; 1991 } 1992 1993 static const struct hda_input_mux cxt5066_olpc_dc_bias = { 1994 .num_items = 3, 1995 .items = { 1996 { "Off", PIN_IN }, 1997 { "50%", PIN_VREF50 }, 1998 { "80%", PIN_VREF80 }, 1999 }, 2000 }; 2001 2002 static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec) 2003 { 2004 struct conexant_spec *spec = codec->spec; 2005 /* Even though port F is the DC input, the bias is controlled on port B. 2006 * we also leave that port as an active input (but unselected) in DC mode 2007 * just in case that is necessary to make the bias setting take effect. */ 2008 return snd_hda_set_pin_ctl_cache(codec, 0x1a, 2009 cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); 2010 } 2011 2012 /* OLPC defers mic widget control until when capture is started because the 2013 * microphone LED comes on as soon as these settings are put in place. if we 2014 * did this before recording, it would give the false indication that recording 2015 * is happening when it is not. */ 2016 static void cxt5066_olpc_select_mic(struct hda_codec *codec) 2017 { 2018 struct conexant_spec *spec = codec->spec; 2019 if (!spec->recording) 2020 return; 2021 2022 if (spec->dc_enable) { 2023 /* in DC mode we ignore presence detection and just use the jack 2024 * through our special DC port */ 2025 const struct hda_verb enable_dc_mode[] = { 2026 /* disble internal mic, port C */ 2027 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2028 2029 /* enable DC capture, port F */ 2030 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2031 {}, 2032 }; 2033 2034 snd_hda_sequence_write(codec, enable_dc_mode); 2035 /* port B input disabled (and bias set) through the following call */ 2036 cxt5066_set_olpc_dc_bias(codec); 2037 return; 2038 } 2039 2040 /* disable DC (port F) */ 2041 snd_hda_set_pin_ctl(codec, 0x1e, 0); 2042 2043 /* external mic, port B */ 2044 snd_hda_set_pin_ctl(codec, 0x1a, 2045 spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); 2046 2047 /* internal mic, port C */ 2048 snd_hda_set_pin_ctl(codec, 0x1b, 2049 spec->ext_mic_present ? 0 : PIN_VREF80); 2050 } 2051 2052 /* toggle input of built-in and mic jack appropriately */ 2053 static void cxt5066_olpc_automic(struct hda_codec *codec) 2054 { 2055 struct conexant_spec *spec = codec->spec; 2056 unsigned int present; 2057 2058 if (spec->dc_enable) /* don't do presence detection in DC mode */ 2059 return; 2060 2061 present = snd_hda_codec_read(codec, 0x1a, 0, 2062 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 2063 if (present) 2064 snd_printdd("CXT5066: external microphone detected\n"); 2065 else 2066 snd_printdd("CXT5066: external microphone absent\n"); 2067 2068 snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, 2069 present ? 0 : 1); 2070 spec->ext_mic_present = !!present; 2071 2072 cxt5066_olpc_select_mic(codec); 2073 } 2074 2075 /* toggle input of built-in digital mic and mic jack appropriately */ 2076 static void cxt5066_vostro_automic(struct hda_codec *codec) 2077 { 2078 unsigned int present; 2079 2080 struct hda_verb ext_mic_present[] = { 2081 /* enable external mic, port B */ 2082 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2083 2084 /* switch to external mic input */ 2085 {0x17, AC_VERB_SET_CONNECT_SEL, 0}, 2086 {0x14, AC_VERB_SET_CONNECT_SEL, 0}, 2087 2088 /* disable internal digital mic */ 2089 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2090 {} 2091 }; 2092 static const struct hda_verb ext_mic_absent[] = { 2093 /* enable internal mic, port C */ 2094 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2095 2096 /* switch to internal mic input */ 2097 {0x14, AC_VERB_SET_CONNECT_SEL, 2}, 2098 2099 /* disable external mic, port B */ 2100 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2101 {} 2102 }; 2103 2104 present = snd_hda_jack_detect(codec, 0x1a); 2105 if (present) { 2106 snd_printdd("CXT5066: external microphone detected\n"); 2107 snd_hda_sequence_write(codec, ext_mic_present); 2108 } else { 2109 snd_printdd("CXT5066: external microphone absent\n"); 2110 snd_hda_sequence_write(codec, ext_mic_absent); 2111 } 2112 } 2113 2114 /* toggle input of built-in digital mic and mic jack appropriately */ 2115 static void cxt5066_ideapad_automic(struct hda_codec *codec) 2116 { 2117 unsigned int present; 2118 2119 struct hda_verb ext_mic_present[] = { 2120 {0x14, AC_VERB_SET_CONNECT_SEL, 0}, 2121 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2122 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2123 {} 2124 }; 2125 static const struct hda_verb ext_mic_absent[] = { 2126 {0x14, AC_VERB_SET_CONNECT_SEL, 2}, 2127 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2128 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2129 {} 2130 }; 2131 2132 present = snd_hda_jack_detect(codec, 0x1b); 2133 if (present) { 2134 snd_printdd("CXT5066: external microphone detected\n"); 2135 snd_hda_sequence_write(codec, ext_mic_present); 2136 } else { 2137 snd_printdd("CXT5066: external microphone absent\n"); 2138 snd_hda_sequence_write(codec, ext_mic_absent); 2139 } 2140 } 2141 2142 2143 /* toggle input of built-in digital mic and mic jack appropriately */ 2144 static void cxt5066_asus_automic(struct hda_codec *codec) 2145 { 2146 unsigned int present; 2147 2148 present = snd_hda_jack_detect(codec, 0x1b); 2149 snd_printdd("CXT5066: external microphone present=%d\n", present); 2150 snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, 2151 present ? 1 : 0); 2152 } 2153 2154 2155 /* toggle input of built-in digital mic and mic jack appropriately */ 2156 static void cxt5066_hp_laptop_automic(struct hda_codec *codec) 2157 { 2158 unsigned int present; 2159 2160 present = snd_hda_jack_detect(codec, 0x1b); 2161 snd_printdd("CXT5066: external microphone present=%d\n", present); 2162 snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, 2163 present ? 1 : 3); 2164 } 2165 2166 2167 /* toggle input of built-in digital mic and mic jack appropriately 2168 order is: external mic -> dock mic -> interal mic */ 2169 static void cxt5066_thinkpad_automic(struct hda_codec *codec) 2170 { 2171 unsigned int ext_present, dock_present; 2172 2173 static const struct hda_verb ext_mic_present[] = { 2174 {0x14, AC_VERB_SET_CONNECT_SEL, 0}, 2175 {0x17, AC_VERB_SET_CONNECT_SEL, 1}, 2176 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2177 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2178 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2179 {} 2180 }; 2181 static const struct hda_verb dock_mic_present[] = { 2182 {0x14, AC_VERB_SET_CONNECT_SEL, 0}, 2183 {0x17, AC_VERB_SET_CONNECT_SEL, 0}, 2184 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2185 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2186 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2187 {} 2188 }; 2189 static const struct hda_verb ext_mic_absent[] = { 2190 {0x14, AC_VERB_SET_CONNECT_SEL, 2}, 2191 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2192 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2193 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2194 {} 2195 }; 2196 2197 ext_present = snd_hda_jack_detect(codec, 0x1b); 2198 dock_present = snd_hda_jack_detect(codec, 0x1a); 2199 if (ext_present) { 2200 snd_printdd("CXT5066: external microphone detected\n"); 2201 snd_hda_sequence_write(codec, ext_mic_present); 2202 } else if (dock_present) { 2203 snd_printdd("CXT5066: dock microphone detected\n"); 2204 snd_hda_sequence_write(codec, dock_mic_present); 2205 } else { 2206 snd_printdd("CXT5066: external microphone absent\n"); 2207 snd_hda_sequence_write(codec, ext_mic_absent); 2208 } 2209 } 2210 2211 /* mute internal speaker if HP is plugged */ 2212 static void cxt5066_hp_automute(struct hda_codec *codec) 2213 { 2214 struct conexant_spec *spec = codec->spec; 2215 unsigned int portA, portD; 2216 2217 /* Port A */ 2218 portA = snd_hda_jack_detect(codec, 0x19); 2219 2220 /* Port D */ 2221 portD = snd_hda_jack_detect(codec, 0x1c); 2222 2223 spec->hp_present = portA ? HP_PRESENT_PORT_A : 0; 2224 spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0; 2225 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", 2226 portA, portD, spec->hp_present); 2227 cxt5066_update_speaker(codec); 2228 } 2229 2230 /* Dispatch the right mic autoswitch function */ 2231 static void cxt5066_automic(struct hda_codec *codec) 2232 { 2233 struct conexant_spec *spec = codec->spec; 2234 2235 if (spec->dell_vostro) 2236 cxt5066_vostro_automic(codec); 2237 else if (spec->ideapad) 2238 cxt5066_ideapad_automic(codec); 2239 else if (spec->thinkpad) 2240 cxt5066_thinkpad_automic(codec); 2241 else if (spec->hp_laptop) 2242 cxt5066_hp_laptop_automic(codec); 2243 else if (spec->asus) 2244 cxt5066_asus_automic(codec); 2245 } 2246 2247 /* unsolicited event for jack sensing */ 2248 static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) 2249 { 2250 struct conexant_spec *spec = codec->spec; 2251 snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); 2252 switch (res >> 26) { 2253 case CONEXANT_HP_EVENT: 2254 cxt5066_hp_automute(codec); 2255 break; 2256 case CONEXANT_MIC_EVENT: 2257 /* ignore mic events in DC mode; we're always using the jack */ 2258 if (!spec->dc_enable) 2259 cxt5066_olpc_automic(codec); 2260 break; 2261 } 2262 } 2263 2264 /* unsolicited event for jack sensing */ 2265 static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) 2266 { 2267 snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); 2268 switch (res >> 26) { 2269 case CONEXANT_HP_EVENT: 2270 cxt5066_hp_automute(codec); 2271 break; 2272 case CONEXANT_MIC_EVENT: 2273 cxt5066_automic(codec); 2274 break; 2275 } 2276 } 2277 2278 2279 static const struct hda_input_mux cxt5066_analog_mic_boost = { 2280 .num_items = 5, 2281 .items = { 2282 { "0dB", 0 }, 2283 { "10dB", 1 }, 2284 { "20dB", 2 }, 2285 { "30dB", 3 }, 2286 { "40dB", 4 }, 2287 }, 2288 }; 2289 2290 static void cxt5066_set_mic_boost(struct hda_codec *codec) 2291 { 2292 struct conexant_spec *spec = codec->spec; 2293 snd_hda_codec_write_cache(codec, 0x17, 0, 2294 AC_VERB_SET_AMP_GAIN_MUTE, 2295 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | 2296 cxt5066_analog_mic_boost.items[spec->mic_boost].index); 2297 if (spec->ideapad || spec->thinkpad) { 2298 /* adjust the internal mic as well...it is not through 0x17 */ 2299 snd_hda_codec_write_cache(codec, 0x23, 0, 2300 AC_VERB_SET_AMP_GAIN_MUTE, 2301 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT | 2302 cxt5066_analog_mic_boost. 2303 items[spec->mic_boost].index); 2304 } 2305 } 2306 2307 static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, 2308 struct snd_ctl_elem_info *uinfo) 2309 { 2310 return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo); 2311 } 2312 2313 static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, 2314 struct snd_ctl_elem_value *ucontrol) 2315 { 2316 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2317 struct conexant_spec *spec = codec->spec; 2318 ucontrol->value.enumerated.item[0] = spec->mic_boost; 2319 return 0; 2320 } 2321 2322 static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, 2323 struct snd_ctl_elem_value *ucontrol) 2324 { 2325 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2326 struct conexant_spec *spec = codec->spec; 2327 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; 2328 unsigned int idx; 2329 idx = ucontrol->value.enumerated.item[0]; 2330 if (idx >= imux->num_items) 2331 idx = imux->num_items - 1; 2332 2333 spec->mic_boost = idx; 2334 if (!spec->dc_enable) 2335 cxt5066_set_mic_boost(codec); 2336 return 1; 2337 } 2338 2339 static void cxt5066_enable_dc(struct hda_codec *codec) 2340 { 2341 const struct hda_verb enable_dc_mode[] = { 2342 /* disable gain */ 2343 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2344 2345 /* switch to DC input */ 2346 {0x17, AC_VERB_SET_CONNECT_SEL, 3}, 2347 {} 2348 }; 2349 2350 /* configure as input source */ 2351 snd_hda_sequence_write(codec, enable_dc_mode); 2352 cxt5066_olpc_select_mic(codec); /* also sets configured bias */ 2353 } 2354 2355 static void cxt5066_disable_dc(struct hda_codec *codec) 2356 { 2357 /* reconfigure input source */ 2358 cxt5066_set_mic_boost(codec); 2359 /* automic also selects the right mic if we're recording */ 2360 cxt5066_olpc_automic(codec); 2361 } 2362 2363 static int cxt5066_olpc_dc_get(struct snd_kcontrol *kcontrol, 2364 struct snd_ctl_elem_value *ucontrol) 2365 { 2366 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2367 struct conexant_spec *spec = codec->spec; 2368 ucontrol->value.integer.value[0] = spec->dc_enable; 2369 return 0; 2370 } 2371 2372 static int cxt5066_olpc_dc_put(struct snd_kcontrol *kcontrol, 2373 struct snd_ctl_elem_value *ucontrol) 2374 { 2375 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2376 struct conexant_spec *spec = codec->spec; 2377 int dc_enable = !!ucontrol->value.integer.value[0]; 2378 2379 if (dc_enable == spec->dc_enable) 2380 return 0; 2381 2382 spec->dc_enable = dc_enable; 2383 if (dc_enable) 2384 cxt5066_enable_dc(codec); 2385 else 2386 cxt5066_disable_dc(codec); 2387 2388 return 1; 2389 } 2390 2391 static int cxt5066_olpc_dc_bias_enum_info(struct snd_kcontrol *kcontrol, 2392 struct snd_ctl_elem_info *uinfo) 2393 { 2394 return snd_hda_input_mux_info(&cxt5066_olpc_dc_bias, uinfo); 2395 } 2396 2397 static int cxt5066_olpc_dc_bias_enum_get(struct snd_kcontrol *kcontrol, 2398 struct snd_ctl_elem_value *ucontrol) 2399 { 2400 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2401 struct conexant_spec *spec = codec->spec; 2402 ucontrol->value.enumerated.item[0] = spec->dc_input_bias; 2403 return 0; 2404 } 2405 2406 static int cxt5066_olpc_dc_bias_enum_put(struct snd_kcontrol *kcontrol, 2407 struct snd_ctl_elem_value *ucontrol) 2408 { 2409 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2410 struct conexant_spec *spec = codec->spec; 2411 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; 2412 unsigned int idx; 2413 2414 idx = ucontrol->value.enumerated.item[0]; 2415 if (idx >= imux->num_items) 2416 idx = imux->num_items - 1; 2417 2418 spec->dc_input_bias = idx; 2419 if (spec->dc_enable) 2420 cxt5066_set_olpc_dc_bias(codec); 2421 return 1; 2422 } 2423 2424 static void cxt5066_olpc_capture_prepare(struct hda_codec *codec) 2425 { 2426 struct conexant_spec *spec = codec->spec; 2427 /* mark as recording and configure the microphone widget so that the 2428 * recording LED comes on. */ 2429 spec->recording = 1; 2430 cxt5066_olpc_select_mic(codec); 2431 } 2432 2433 static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec) 2434 { 2435 struct conexant_spec *spec = codec->spec; 2436 const struct hda_verb disable_mics[] = { 2437 /* disable external mic, port B */ 2438 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2439 2440 /* disble internal mic, port C */ 2441 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2442 2443 /* disable DC capture, port F */ 2444 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2445 {}, 2446 }; 2447 2448 snd_hda_sequence_write(codec, disable_mics); 2449 spec->recording = 0; 2450 } 2451 2452 static void conexant_check_dig_outs(struct hda_codec *codec, 2453 const hda_nid_t *dig_pins, 2454 int num_pins) 2455 { 2456 struct conexant_spec *spec = codec->spec; 2457 hda_nid_t *nid_loc = &spec->multiout.dig_out_nid; 2458 int i; 2459 2460 for (i = 0; i < num_pins; i++, dig_pins++) { 2461 unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins); 2462 if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE) 2463 continue; 2464 if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1) 2465 continue; 2466 } 2467 } 2468 2469 static const struct hda_input_mux cxt5066_capture_source = { 2470 .num_items = 4, 2471 .items = { 2472 { "Mic B", 0 }, 2473 { "Mic C", 1 }, 2474 { "Mic E", 2 }, 2475 { "Mic F", 3 }, 2476 }, 2477 }; 2478 2479 static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = { 2480 .ops = &snd_hda_bind_vol, 2481 .values = { 2482 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), 2483 HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), 2484 0 2485 }, 2486 }; 2487 2488 static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = { 2489 .ops = &snd_hda_bind_sw, 2490 .values = { 2491 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), 2492 HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), 2493 0 2494 }, 2495 }; 2496 2497 static const struct snd_kcontrol_new cxt5066_mixer_master[] = { 2498 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), 2499 {} 2500 }; 2501 2502 static const struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { 2503 { 2504 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2505 .name = "Master Playback Volume", 2506 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 2507 SNDRV_CTL_ELEM_ACCESS_TLV_READ | 2508 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, 2509 .subdevice = HDA_SUBDEV_AMP_FLAG, 2510 .info = snd_hda_mixer_amp_volume_info, 2511 .get = snd_hda_mixer_amp_volume_get, 2512 .put = snd_hda_mixer_amp_volume_put, 2513 .tlv = { .c = snd_hda_mixer_amp_tlv }, 2514 /* offset by 28 volume steps to limit minimum gain to -46dB */ 2515 .private_value = 2516 HDA_COMPOSE_AMP_VAL_OFS(0x10, 3, 0, HDA_OUTPUT, 28), 2517 }, 2518 {} 2519 }; 2520 2521 static const struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = { 2522 { 2523 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2524 .name = "DC Mode Enable Switch", 2525 .info = snd_ctl_boolean_mono_info, 2526 .get = cxt5066_olpc_dc_get, 2527 .put = cxt5066_olpc_dc_put, 2528 }, 2529 { 2530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2531 .name = "DC Input Bias Enum", 2532 .info = cxt5066_olpc_dc_bias_enum_info, 2533 .get = cxt5066_olpc_dc_bias_enum_get, 2534 .put = cxt5066_olpc_dc_bias_enum_put, 2535 }, 2536 {} 2537 }; 2538 2539 static const struct snd_kcontrol_new cxt5066_mixers[] = { 2540 { 2541 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2542 .name = "Master Playback Switch", 2543 .info = cxt_eapd_info, 2544 .get = cxt_eapd_get, 2545 .put = cxt5066_hp_master_sw_put, 2546 .private_value = 0x1d, 2547 }, 2548 2549 { 2550 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2551 .name = "Analog Mic Boost Capture Enum", 2552 .info = cxt5066_mic_boost_mux_enum_info, 2553 .get = cxt5066_mic_boost_mux_enum_get, 2554 .put = cxt5066_mic_boost_mux_enum_put, 2555 }, 2556 2557 HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), 2558 HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others), 2559 {} 2560 }; 2561 2562 static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = { 2563 { 2564 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2565 .name = "Internal Mic Boost Capture Enum", 2566 .info = cxt5066_mic_boost_mux_enum_info, 2567 .get = cxt5066_mic_boost_mux_enum_get, 2568 .put = cxt5066_mic_boost_mux_enum_put, 2569 .private_value = 0x23 | 0x100, 2570 }, 2571 {} 2572 }; 2573 2574 static const struct hda_verb cxt5066_init_verbs[] = { 2575 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ 2576 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ 2577 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ 2578 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ 2579 2580 /* Speakers */ 2581 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2582 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2583 2584 /* HP, Amp */ 2585 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2586 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2587 2588 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2589 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2590 2591 /* DAC1 */ 2592 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2593 2594 /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ 2595 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, 2596 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2597 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, 2598 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2599 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2600 2601 /* no digital microphone support yet */ 2602 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2603 2604 /* Audio input selector */ 2605 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, 2606 2607 /* SPDIF route: PCM */ 2608 {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, 2609 {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, 2610 2611 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2612 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2613 2614 /* EAPD */ 2615 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 2616 2617 /* not handling these yet */ 2618 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, 2619 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, 2620 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, 2621 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, 2622 {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, 2623 {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, 2624 {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, 2625 {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, 2626 { } /* end */ 2627 }; 2628 2629 static const struct hda_verb cxt5066_init_verbs_olpc[] = { 2630 /* Port A: headphones */ 2631 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2632 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2633 2634 /* Port B: external microphone */ 2635 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2636 2637 /* Port C: internal microphone */ 2638 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2639 2640 /* Port D: unused */ 2641 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2642 2643 /* Port E: unused, but has primary EAPD */ 2644 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2645 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 2646 2647 /* Port F: external DC input through microphone port */ 2648 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2649 2650 /* Port G: internal speakers */ 2651 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2652 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2653 2654 /* DAC1 */ 2655 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2656 2657 /* DAC2: unused */ 2658 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2659 2660 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, 2661 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2662 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2663 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2664 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2665 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2666 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2667 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2668 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2669 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2670 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2671 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2672 2673 /* Disable digital microphone port */ 2674 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2675 2676 /* Audio input selectors */ 2677 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, 2678 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2679 2680 /* Disable SPDIF */ 2681 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2682 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2683 2684 /* enable unsolicited events for Port A and B */ 2685 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 2686 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 2687 { } /* end */ 2688 }; 2689 2690 static const struct hda_verb cxt5066_init_verbs_vostro[] = { 2691 /* Port A: headphones */ 2692 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2693 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2694 2695 /* Port B: external microphone */ 2696 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2697 2698 /* Port C: unused */ 2699 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2700 2701 /* Port D: unused */ 2702 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2703 2704 /* Port E: unused, but has primary EAPD */ 2705 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2706 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 2707 2708 /* Port F: unused */ 2709 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2710 2711 /* Port G: internal speakers */ 2712 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2713 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2714 2715 /* DAC1 */ 2716 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2717 2718 /* DAC2: unused */ 2719 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 2720 2721 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2722 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2723 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2724 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2725 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2726 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2727 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2728 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2729 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 2730 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2731 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 2732 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2733 2734 /* Digital microphone port */ 2735 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2736 2737 /* Audio input selectors */ 2738 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, 2739 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, 2740 2741 /* Disable SPDIF */ 2742 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2743 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2744 2745 /* enable unsolicited events for Port A and B */ 2746 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 2747 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 2748 { } /* end */ 2749 }; 2750 2751 static const struct hda_verb cxt5066_init_verbs_ideapad[] = { 2752 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ 2753 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ 2754 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ 2755 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ 2756 2757 /* Speakers */ 2758 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2759 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2760 2761 /* HP, Amp */ 2762 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2763 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2764 2765 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2766 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2767 2768 /* DAC1 */ 2769 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2770 2771 /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ 2772 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, 2773 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2774 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, 2775 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2776 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2777 {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ 2778 2779 /* Audio input selector */ 2780 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, 2781 {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ 2782 2783 /* SPDIF route: PCM */ 2784 {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, 2785 {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, 2786 2787 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2788 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2789 2790 /* internal microphone */ 2791 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ 2792 2793 /* EAPD */ 2794 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 2795 2796 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 2797 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 2798 { } /* end */ 2799 }; 2800 2801 static const struct hda_verb cxt5066_init_verbs_thinkpad[] = { 2802 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ 2803 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ 2804 2805 /* Port G: internal speakers */ 2806 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2807 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2808 2809 /* Port A: HP, Amp */ 2810 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2811 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2812 2813 /* Port B: Mic Dock */ 2814 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2815 2816 /* Port C: Mic */ 2817 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2818 2819 /* Port D: HP Dock, Amp */ 2820 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2821 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2822 2823 /* DAC1 */ 2824 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 2825 2826 /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ 2827 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, 2828 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, 2829 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, 2830 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 2831 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 2832 {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ 2833 2834 /* Audio input selector */ 2835 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, 2836 {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ 2837 2838 /* SPDIF route: PCM */ 2839 {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, 2840 {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, 2841 2842 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2843 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2844 2845 /* internal microphone */ 2846 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ 2847 2848 /* EAPD */ 2849 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 2850 2851 /* enable unsolicited events for Port A, B, C and D */ 2852 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 2853 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 2854 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 2855 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 2856 { } /* end */ 2857 }; 2858 2859 static const struct hda_verb cxt5066_init_verbs_portd_lo[] = { 2860 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2861 { } /* end */ 2862 }; 2863 2864 2865 static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = { 2866 {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, 2867 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 2868 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 2869 { } /* end */ 2870 }; 2871 2872 /* initialize jack-sensing, too */ 2873 static int cxt5066_init(struct hda_codec *codec) 2874 { 2875 snd_printdd("CXT5066: init\n"); 2876 conexant_init(codec); 2877 if (codec->patch_ops.unsol_event) { 2878 cxt5066_hp_automute(codec); 2879 cxt5066_automic(codec); 2880 } 2881 cxt5066_set_mic_boost(codec); 2882 return 0; 2883 } 2884 2885 static int cxt5066_olpc_init(struct hda_codec *codec) 2886 { 2887 struct conexant_spec *spec = codec->spec; 2888 snd_printdd("CXT5066: init\n"); 2889 conexant_init(codec); 2890 cxt5066_hp_automute(codec); 2891 if (!spec->dc_enable) { 2892 cxt5066_set_mic_boost(codec); 2893 cxt5066_olpc_automic(codec); 2894 } else { 2895 cxt5066_enable_dc(codec); 2896 } 2897 return 0; 2898 } 2899 2900 enum { 2901 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 2902 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 2903 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ 2904 CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ 2905 CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ 2906 CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ 2907 CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */ 2908 CXT5066_HP_LAPTOP, /* HP Laptop */ 2909 CXT5066_AUTO, /* BIOS auto-parser */ 2910 CXT5066_MODELS 2911 }; 2912 2913 static const char * const cxt5066_models[CXT5066_MODELS] = { 2914 [CXT5066_LAPTOP] = "laptop", 2915 [CXT5066_DELL_LAPTOP] = "dell-laptop", 2916 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", 2917 [CXT5066_DELL_VOSTRO] = "dell-vostro", 2918 [CXT5066_IDEAPAD] = "ideapad", 2919 [CXT5066_THINKPAD] = "thinkpad", 2920 [CXT5066_ASUS] = "asus", 2921 [CXT5066_HP_LAPTOP] = "hp-laptop", 2922 [CXT5066_AUTO] = "auto", 2923 }; 2924 2925 static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { 2926 SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), 2927 SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), 2928 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), 2929 SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), 2930 SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), 2931 SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), 2932 SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD), 2933 SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), 2934 SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS), 2935 SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS), 2936 SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), 2937 SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), 2938 SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), 2939 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", 2940 CXT5066_LAPTOP), 2941 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), 2942 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), 2943 SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), 2944 SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), 2945 SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD), 2946 SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), 2947 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), 2948 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), 2949 {} 2950 }; 2951 2952 static int patch_cxt5066(struct hda_codec *codec) 2953 { 2954 struct conexant_spec *spec; 2955 int board_config; 2956 2957 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS, 2958 cxt5066_models, cxt5066_cfg_tbl); 2959 if (board_config < 0) 2960 board_config = CXT5066_AUTO; /* model=auto as default */ 2961 if (board_config == CXT5066_AUTO) 2962 return patch_conexant_auto(codec); 2963 2964 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 2965 if (!spec) 2966 return -ENOMEM; 2967 codec->spec = spec; 2968 2969 codec->patch_ops = conexant_patch_ops; 2970 codec->patch_ops.init = conexant_init; 2971 2972 spec->dell_automute = 0; 2973 spec->multiout.max_channels = 2; 2974 spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids); 2975 spec->multiout.dac_nids = cxt5066_dac_nids; 2976 conexant_check_dig_outs(codec, cxt5066_digout_pin_nids, 2977 ARRAY_SIZE(cxt5066_digout_pin_nids)); 2978 spec->num_adc_nids = 1; 2979 spec->adc_nids = cxt5066_adc_nids; 2980 spec->capsrc_nids = cxt5066_capsrc_nids; 2981 spec->input_mux = &cxt5066_capture_source; 2982 2983 spec->port_d_mode = PIN_HP; 2984 2985 spec->num_init_verbs = 1; 2986 spec->init_verbs[0] = cxt5066_init_verbs; 2987 spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes); 2988 spec->channel_mode = cxt5066_modes; 2989 spec->cur_adc = 0; 2990 spec->cur_adc_idx = 0; 2991 2992 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); 2993 2994 switch (board_config) { 2995 default: 2996 case CXT5066_LAPTOP: 2997 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; 2998 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 2999 break; 3000 case CXT5066_DELL_LAPTOP: 3001 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; 3002 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3003 3004 spec->port_d_mode = PIN_OUT; 3005 spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo; 3006 spec->num_init_verbs++; 3007 spec->dell_automute = 1; 3008 break; 3009 case CXT5066_ASUS: 3010 case CXT5066_HP_LAPTOP: 3011 codec->patch_ops.init = cxt5066_init; 3012 codec->patch_ops.unsol_event = cxt5066_unsol_event; 3013 spec->init_verbs[spec->num_init_verbs] = 3014 cxt5066_init_verbs_hp_laptop; 3015 spec->num_init_verbs++; 3016 spec->hp_laptop = board_config == CXT5066_HP_LAPTOP; 3017 spec->asus = board_config == CXT5066_ASUS; 3018 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; 3019 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3020 /* no S/PDIF out */ 3021 if (board_config == CXT5066_HP_LAPTOP) 3022 spec->multiout.dig_out_nid = 0; 3023 /* input source automatically selected */ 3024 spec->input_mux = NULL; 3025 spec->port_d_mode = 0; 3026 spec->mic_boost = 3; /* default 30dB gain */ 3027 break; 3028 3029 case CXT5066_OLPC_XO_1_5: 3030 codec->patch_ops.init = cxt5066_olpc_init; 3031 codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; 3032 spec->init_verbs[0] = cxt5066_init_verbs_olpc; 3033 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; 3034 spec->mixers[spec->num_mixers++] = cxt5066_mixer_olpc_dc; 3035 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3036 spec->port_d_mode = 0; 3037 spec->mic_boost = 3; /* default 30dB gain */ 3038 3039 /* no S/PDIF out */ 3040 spec->multiout.dig_out_nid = 0; 3041 3042 /* input source automatically selected */ 3043 spec->input_mux = NULL; 3044 3045 /* our capture hooks which allow us to turn on the microphone LED 3046 * at the right time */ 3047 spec->capture_prepare = cxt5066_olpc_capture_prepare; 3048 spec->capture_cleanup = cxt5066_olpc_capture_cleanup; 3049 break; 3050 case CXT5066_DELL_VOSTRO: 3051 codec->patch_ops.init = cxt5066_init; 3052 codec->patch_ops.unsol_event = cxt5066_unsol_event; 3053 spec->init_verbs[0] = cxt5066_init_verbs_vostro; 3054 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; 3055 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3056 spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; 3057 spec->port_d_mode = 0; 3058 spec->dell_vostro = 1; 3059 spec->mic_boost = 3; /* default 30dB gain */ 3060 3061 /* no S/PDIF out */ 3062 spec->multiout.dig_out_nid = 0; 3063 3064 /* input source automatically selected */ 3065 spec->input_mux = NULL; 3066 break; 3067 case CXT5066_IDEAPAD: 3068 codec->patch_ops.init = cxt5066_init; 3069 codec->patch_ops.unsol_event = cxt5066_unsol_event; 3070 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; 3071 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3072 spec->init_verbs[0] = cxt5066_init_verbs_ideapad; 3073 spec->port_d_mode = 0; 3074 spec->ideapad = 1; 3075 spec->mic_boost = 2; /* default 20dB gain */ 3076 3077 /* no S/PDIF out */ 3078 spec->multiout.dig_out_nid = 0; 3079 3080 /* input source automatically selected */ 3081 spec->input_mux = NULL; 3082 break; 3083 case CXT5066_THINKPAD: 3084 codec->patch_ops.init = cxt5066_init; 3085 codec->patch_ops.unsol_event = cxt5066_unsol_event; 3086 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; 3087 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3088 spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; 3089 spec->thinkpad = 1; 3090 spec->port_d_mode = PIN_OUT; 3091 spec->mic_boost = 2; /* default 20dB gain */ 3092 3093 /* no S/PDIF out */ 3094 spec->multiout.dig_out_nid = 0; 3095 3096 /* input source automatically selected */ 3097 spec->input_mux = NULL; 3098 break; 3099 } 3100 3101 if (spec->beep_amp) 3102 snd_hda_attach_beep_device(codec, spec->beep_amp); 3103 3104 return 0; 3105 } 3106 3107 #endif /* ENABLE_CXT_STATIC_QUIRKS */ 3108 3109 3110 /* 3111 * Automatic parser for CX20641 & co 3112 */ 3113 3114 #ifdef CONFIG_SND_HDA_INPUT_BEEP 3115 static void cx_auto_parse_beep(struct hda_codec *codec) 3116 { 3117 struct conexant_spec *spec = codec->spec; 3118 hda_nid_t nid, end_nid; 3119 3120 end_nid = codec->start_nid + codec->num_nodes; 3121 for (nid = codec->start_nid; nid < end_nid; nid++) 3122 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) { 3123 set_beep_amp(spec, nid, 0, HDA_OUTPUT); 3124 break; 3125 } 3126 } 3127 #else 3128 #define cx_auto_parse_beep(codec) 3129 #endif 3130 3131 /* parse EAPDs */ 3132 static void cx_auto_parse_eapd(struct hda_codec *codec) 3133 { 3134 struct conexant_spec *spec = codec->spec; 3135 hda_nid_t nid, end_nid; 3136 3137 end_nid = codec->start_nid + codec->num_nodes; 3138 for (nid = codec->start_nid; nid < end_nid; nid++) { 3139 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) 3140 continue; 3141 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) 3142 continue; 3143 spec->eapds[spec->num_eapds++] = nid; 3144 if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) 3145 break; 3146 } 3147 3148 /* NOTE: below is a wild guess; if we have more than two EAPDs, 3149 * it's a new chip, where EAPDs are supposed to be associated to 3150 * pins, and we can control EAPD per pin. 3151 * OTOH, if only one or two EAPDs are found, it's an old chip, 3152 * thus it might control over all pins. 3153 */ 3154 if (spec->num_eapds > 2) 3155 spec->gen.own_eapd_ctl = 1; 3156 } 3157 3158 static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins, 3159 hda_nid_t *pins, bool on) 3160 { 3161 int i; 3162 for (i = 0; i < num_pins; i++) { 3163 if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD) 3164 snd_hda_codec_write(codec, pins[i], 0, 3165 AC_VERB_SET_EAPD_BTLENABLE, 3166 on ? 0x02 : 0); 3167 } 3168 } 3169 3170 /* turn on/off EAPD according to Master switch */ 3171 static void cx_auto_vmaster_hook(void *private_data, int enabled) 3172 { 3173 struct hda_codec *codec = private_data; 3174 struct conexant_spec *spec = codec->spec; 3175 3176 cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled); 3177 } 3178 3179 static int cx_auto_build_controls(struct hda_codec *codec) 3180 { 3181 int err; 3182 3183 err = snd_hda_gen_build_controls(codec); 3184 if (err < 0) 3185 return err; 3186 3187 err = add_beep_ctls(codec); 3188 if (err < 0) 3189 return err; 3190 3191 return 0; 3192 } 3193 3194 static const struct hda_codec_ops cx_auto_patch_ops = { 3195 .build_controls = cx_auto_build_controls, 3196 .build_pcms = snd_hda_gen_build_pcms, 3197 .init = snd_hda_gen_init, 3198 .free = snd_hda_gen_free, 3199 .unsol_event = snd_hda_jack_unsol_event, 3200 #ifdef CONFIG_PM 3201 .check_power_status = snd_hda_gen_check_power_status, 3202 #endif 3203 }; 3204 3205 /* 3206 * pin fix-up 3207 */ 3208 enum { 3209 CXT_PINCFG_LENOVO_X200, 3210 CXT_PINCFG_LENOVO_TP410, 3211 CXT_PINCFG_LEMOTE_A1004, 3212 CXT_PINCFG_LEMOTE_A1205, 3213 CXT_FIXUP_STEREO_DMIC, 3214 CXT_FIXUP_INC_MIC_BOOST, 3215 }; 3216 3217 static void cxt_fixup_stereo_dmic(struct hda_codec *codec, 3218 const struct hda_fixup *fix, int action) 3219 { 3220 struct conexant_spec *spec = codec->spec; 3221 spec->gen.inv_dmic_split = 1; 3222 } 3223 3224 static void cxt5066_increase_mic_boost(struct hda_codec *codec, 3225 const struct hda_fixup *fix, int action) 3226 { 3227 if (action != HDA_FIXUP_ACT_PRE_PROBE) 3228 return; 3229 3230 snd_hda_override_amp_caps(codec, 0x17, HDA_OUTPUT, 3231 (0x3 << AC_AMPCAP_OFFSET_SHIFT) | 3232 (0x4 << AC_AMPCAP_NUM_STEPS_SHIFT) | 3233 (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | 3234 (0 << AC_AMPCAP_MUTE_SHIFT)); 3235 } 3236 3237 /* ThinkPad X200 & co with cxt5051 */ 3238 static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = { 3239 { 0x16, 0x042140ff }, /* HP (seq# overridden) */ 3240 { 0x17, 0x21a11000 }, /* dock-mic */ 3241 { 0x19, 0x2121103f }, /* dock-HP */ 3242 { 0x1c, 0x21440100 }, /* dock SPDIF out */ 3243 {} 3244 }; 3245 3246 /* ThinkPad 410/420/510/520, X201 & co with cxt5066 */ 3247 static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = { 3248 { 0x19, 0x042110ff }, /* HP (seq# overridden) */ 3249 { 0x1a, 0x21a190f0 }, /* dock-mic */ 3250 { 0x1c, 0x212140ff }, /* dock-HP */ 3251 {} 3252 }; 3253 3254 /* Lemote A1004/A1205 with cxt5066 */ 3255 static const struct hda_pintbl cxt_pincfg_lemote[] = { 3256 { 0x1a, 0x90a10020 }, /* Internal mic */ 3257 { 0x1b, 0x03a11020 }, /* External mic */ 3258 { 0x1d, 0x400101f0 }, /* Not used */ 3259 { 0x1e, 0x40a701f0 }, /* Not used */ 3260 { 0x20, 0x404501f0 }, /* Not used */ 3261 { 0x22, 0x404401f0 }, /* Not used */ 3262 { 0x23, 0x40a701f0 }, /* Not used */ 3263 {} 3264 }; 3265 3266 static const struct hda_fixup cxt_fixups[] = { 3267 [CXT_PINCFG_LENOVO_X200] = { 3268 .type = HDA_FIXUP_PINS, 3269 .v.pins = cxt_pincfg_lenovo_x200, 3270 }, 3271 [CXT_PINCFG_LENOVO_TP410] = { 3272 .type = HDA_FIXUP_PINS, 3273 .v.pins = cxt_pincfg_lenovo_tp410, 3274 }, 3275 [CXT_PINCFG_LEMOTE_A1004] = { 3276 .type = HDA_FIXUP_PINS, 3277 .chained = true, 3278 .chain_id = CXT_FIXUP_INC_MIC_BOOST, 3279 .v.pins = cxt_pincfg_lemote, 3280 }, 3281 [CXT_PINCFG_LEMOTE_A1205] = { 3282 .type = HDA_FIXUP_PINS, 3283 .v.pins = cxt_pincfg_lemote, 3284 }, 3285 [CXT_FIXUP_STEREO_DMIC] = { 3286 .type = HDA_FIXUP_FUNC, 3287 .v.func = cxt_fixup_stereo_dmic, 3288 }, 3289 [CXT_FIXUP_INC_MIC_BOOST] = { 3290 .type = HDA_FIXUP_FUNC, 3291 .v.func = cxt5066_increase_mic_boost, 3292 }, 3293 }; 3294 3295 static const struct snd_pci_quirk cxt5051_fixups[] = { 3296 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200), 3297 {} 3298 }; 3299 3300 static const struct snd_pci_quirk cxt5066_fixups[] = { 3301 SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC), 3302 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), 3303 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410), 3304 SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), 3305 SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), 3306 SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), 3307 SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), 3308 SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), 3309 SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), 3310 SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004), 3311 SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205), 3312 {} 3313 }; 3314 3315 /* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches 3316 * can be created (bko#42825) 3317 */ 3318 static void add_cx5051_fake_mutes(struct hda_codec *codec) 3319 { 3320 static hda_nid_t out_nids[] = { 3321 0x10, 0x11, 0 3322 }; 3323 hda_nid_t *p; 3324 3325 for (p = out_nids; *p; p++) 3326 snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT, 3327 AC_AMPCAP_MIN_MUTE | 3328 query_amp_caps(codec, *p, HDA_OUTPUT)); 3329 } 3330 3331 static int patch_conexant_auto(struct hda_codec *codec) 3332 { 3333 struct conexant_spec *spec; 3334 int err; 3335 3336 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", 3337 codec->chip_name); 3338 3339 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3340 if (!spec) 3341 return -ENOMEM; 3342 snd_hda_gen_spec_init(&spec->gen); 3343 codec->spec = spec; 3344 3345 cx_auto_parse_beep(codec); 3346 cx_auto_parse_eapd(codec); 3347 if (spec->gen.own_eapd_ctl) 3348 spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook; 3349 3350 switch (codec->vendor_id) { 3351 case 0x14f15045: 3352 codec->single_adc_amp = 1; 3353 codec->power_filter = NULL; /* Needs speaker amp to D3 to avoid click */ 3354 break; 3355 case 0x14f15047: 3356 codec->pin_amp_workaround = 1; 3357 spec->gen.mixer_nid = 0x19; 3358 break; 3359 case 0x14f15051: 3360 add_cx5051_fake_mutes(codec); 3361 codec->pin_amp_workaround = 1; 3362 snd_hda_pick_fixup(codec, NULL, cxt5051_fixups, cxt_fixups); 3363 break; 3364 default: 3365 codec->pin_amp_workaround = 1; 3366 snd_hda_pick_fixup(codec, NULL, cxt5066_fixups, cxt_fixups); 3367 break; 3368 } 3369 3370 /* Show mute-led control only on HP laptops 3371 * This is a sort of white-list: on HP laptops, EAPD corresponds 3372 * only to the mute-LED without actualy amp function. Meanwhile, 3373 * others may use EAPD really as an amp switch, so it might be 3374 * not good to expose it blindly. 3375 */ 3376 switch (codec->subsystem_id >> 16) { 3377 case 0x103c: 3378 spec->gen.vmaster_mute_enum = 1; 3379 break; 3380 } 3381 3382 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 3383 3384 err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); 3385 if (err < 0) 3386 goto error; 3387 3388 err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); 3389 if (err < 0) 3390 goto error; 3391 3392 codec->patch_ops = cx_auto_patch_ops; 3393 if (spec->beep_amp) 3394 snd_hda_attach_beep_device(codec, spec->beep_amp); 3395 3396 /* Some laptops with Conexant chips show stalls in S3 resume, 3397 * which falls into the single-cmd mode. 3398 * Better to make reset, then. 3399 */ 3400 if (!codec->bus->sync_write) { 3401 snd_printd("hda_codec: " 3402 "Enable sync_write for stable communication\n"); 3403 codec->bus->sync_write = 1; 3404 codec->bus->allow_bus_reset = 1; 3405 } 3406 3407 return 0; 3408 3409 error: 3410 snd_hda_gen_free(codec); 3411 return err; 3412 } 3413 3414 #ifndef ENABLE_CXT_STATIC_QUIRKS 3415 #define patch_cxt5045 patch_conexant_auto 3416 #define patch_cxt5047 patch_conexant_auto 3417 #define patch_cxt5051 patch_conexant_auto 3418 #define patch_cxt5066 patch_conexant_auto 3419 #endif 3420 3421 /* 3422 */ 3423 3424 static const struct hda_codec_preset snd_hda_preset_conexant[] = { 3425 { .id = 0x14f15045, .name = "CX20549 (Venice)", 3426 .patch = patch_cxt5045 }, 3427 { .id = 0x14f15047, .name = "CX20551 (Waikiki)", 3428 .patch = patch_cxt5047 }, 3429 { .id = 0x14f15051, .name = "CX20561 (Hermosa)", 3430 .patch = patch_cxt5051 }, 3431 { .id = 0x14f15066, .name = "CX20582 (Pebble)", 3432 .patch = patch_cxt5066 }, 3433 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", 3434 .patch = patch_cxt5066 }, 3435 { .id = 0x14f15068, .name = "CX20584", 3436 .patch = patch_cxt5066 }, 3437 { .id = 0x14f15069, .name = "CX20585", 3438 .patch = patch_cxt5066 }, 3439 { .id = 0x14f1506c, .name = "CX20588", 3440 .patch = patch_cxt5066 }, 3441 { .id = 0x14f1506e, .name = "CX20590", 3442 .patch = patch_cxt5066 }, 3443 { .id = 0x14f15097, .name = "CX20631", 3444 .patch = patch_conexant_auto }, 3445 { .id = 0x14f15098, .name = "CX20632", 3446 .patch = patch_conexant_auto }, 3447 { .id = 0x14f150a1, .name = "CX20641", 3448 .patch = patch_conexant_auto }, 3449 { .id = 0x14f150a2, .name = "CX20642", 3450 .patch = patch_conexant_auto }, 3451 { .id = 0x14f150ab, .name = "CX20651", 3452 .patch = patch_conexant_auto }, 3453 { .id = 0x14f150ac, .name = "CX20652", 3454 .patch = patch_conexant_auto }, 3455 { .id = 0x14f150b8, .name = "CX20664", 3456 .patch = patch_conexant_auto }, 3457 { .id = 0x14f150b9, .name = "CX20665", 3458 .patch = patch_conexant_auto }, 3459 { .id = 0x14f1510f, .name = "CX20751/2", 3460 .patch = patch_conexant_auto }, 3461 { .id = 0x14f15110, .name = "CX20751/2", 3462 .patch = patch_conexant_auto }, 3463 { .id = 0x14f15111, .name = "CX20753/4", 3464 .patch = patch_conexant_auto }, 3465 { .id = 0x14f15113, .name = "CX20755", 3466 .patch = patch_conexant_auto }, 3467 { .id = 0x14f15114, .name = "CX20756", 3468 .patch = patch_conexant_auto }, 3469 { .id = 0x14f15115, .name = "CX20757", 3470 .patch = patch_conexant_auto }, 3471 {} /* terminator */ 3472 }; 3473 3474 MODULE_ALIAS("snd-hda-codec-id:14f15045"); 3475 MODULE_ALIAS("snd-hda-codec-id:14f15047"); 3476 MODULE_ALIAS("snd-hda-codec-id:14f15051"); 3477 MODULE_ALIAS("snd-hda-codec-id:14f15066"); 3478 MODULE_ALIAS("snd-hda-codec-id:14f15067"); 3479 MODULE_ALIAS("snd-hda-codec-id:14f15068"); 3480 MODULE_ALIAS("snd-hda-codec-id:14f15069"); 3481 MODULE_ALIAS("snd-hda-codec-id:14f1506c"); 3482 MODULE_ALIAS("snd-hda-codec-id:14f1506e"); 3483 MODULE_ALIAS("snd-hda-codec-id:14f15097"); 3484 MODULE_ALIAS("snd-hda-codec-id:14f15098"); 3485 MODULE_ALIAS("snd-hda-codec-id:14f150a1"); 3486 MODULE_ALIAS("snd-hda-codec-id:14f150a2"); 3487 MODULE_ALIAS("snd-hda-codec-id:14f150ab"); 3488 MODULE_ALIAS("snd-hda-codec-id:14f150ac"); 3489 MODULE_ALIAS("snd-hda-codec-id:14f150b8"); 3490 MODULE_ALIAS("snd-hda-codec-id:14f150b9"); 3491 MODULE_ALIAS("snd-hda-codec-id:14f1510f"); 3492 MODULE_ALIAS("snd-hda-codec-id:14f15110"); 3493 MODULE_ALIAS("snd-hda-codec-id:14f15111"); 3494 MODULE_ALIAS("snd-hda-codec-id:14f15113"); 3495 MODULE_ALIAS("snd-hda-codec-id:14f15114"); 3496 MODULE_ALIAS("snd-hda-codec-id:14f15115"); 3497 3498 MODULE_LICENSE("GPL"); 3499 MODULE_DESCRIPTION("Conexant HD-audio codec"); 3500 3501 static struct hda_codec_preset_list conexant_list = { 3502 .preset = snd_hda_preset_conexant, 3503 .owner = THIS_MODULE, 3504 }; 3505 3506 static int __init patch_conexant_init(void) 3507 { 3508 return snd_hda_add_codec_preset(&conexant_list); 3509 } 3510 3511 static void __exit patch_conexant_exit(void) 3512 { 3513 snd_hda_delete_codec_preset(&conexant_list); 3514 } 3515 3516 module_init(patch_conexant_init) 3517 module_exit(patch_conexant_exit) 3518