linux/sound/pci/hda/patch_analog.c
<<
>>
Prefs
   1/*
   2 * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
   3 *   AD1986A, AD1988
   4 *
   5 * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
   6 *
   7 *  This driver is free software; you can redistribute it and/or modify
   8 *  it under the terms of the GNU General Public License as published by
   9 *  the Free Software Foundation; either version 2 of the License, or
  10 *  (at your option) any later version.
  11 *
  12 *  This driver is distributed in the hope that it will be useful,
  13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 *  GNU General Public License for more details.
  16 *
  17 *  You should have received a copy of the GNU General Public License
  18 *  along with this program; if not, write to the Free Software
  19 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  20 */
  21
  22#include <linux/init.h>
  23#include <linux/slab.h>
  24#include <linux/pci.h>
  25#include <linux/module.h>
  26
  27#include <sound/core.h>
  28#include "hda_codec.h"
  29#include "hda_local.h"
  30#include "hda_auto_parser.h"
  31#include "hda_beep.h"
  32#include "hda_jack.h"
  33#include "hda_generic.h"
  34
  35#define ENABLE_AD_STATIC_QUIRKS
  36
  37struct ad198x_spec {
  38        struct hda_gen_spec gen;
  39
  40        /* for auto parser */
  41        int smux_paths[4];
  42        unsigned int cur_smux;
  43        hda_nid_t eapd_nid;
  44
  45        unsigned int beep_amp;  /* beep amp value, set via set_beep_amp() */
  46
  47#ifdef ENABLE_AD_STATIC_QUIRKS
  48        const struct snd_kcontrol_new *mixers[6];
  49        int num_mixers;
  50        const struct hda_verb *init_verbs[6];   /* initialization verbs
  51                                                 * don't forget NULL termination!
  52                                                 */
  53        unsigned int num_init_verbs;
  54
  55        /* playback */
  56        struct hda_multi_out multiout;  /* playback set-up
  57                                         * max_channels, dacs must be set
  58                                         * dig_out_nid and hp_nid are optional
  59                                         */
  60        unsigned int cur_eapd;
  61        unsigned int need_dac_fix;
  62
  63        /* capture */
  64        unsigned int num_adc_nids;
  65        const hda_nid_t *adc_nids;
  66        hda_nid_t dig_in_nid;           /* digital-in NID; optional */
  67
  68        /* capture source */
  69        const struct hda_input_mux *input_mux;
  70        const hda_nid_t *capsrc_nids;
  71        unsigned int cur_mux[3];
  72
  73        /* channel model */
  74        const struct hda_channel_mode *channel_mode;
  75        int num_channel_mode;
  76
  77        /* PCM information */
  78        struct hda_pcm pcm_rec[3];      /* used in alc_build_pcms() */
  79
  80        unsigned int spdif_route;
  81
  82        unsigned int jack_present: 1;
  83        unsigned int inv_jack_detect: 1;/* inverted jack-detection */
  84        unsigned int analog_beep: 1;    /* analog beep input present */
  85        unsigned int avoid_init_slave_vol:1;
  86
  87#ifdef CONFIG_PM
  88        struct hda_loopback_check loopback;
  89#endif
  90        /* for virtual master */
  91        hda_nid_t vmaster_nid;
  92        const char * const *slave_vols;
  93        const char * const *slave_sws;
  94#endif /* ENABLE_AD_STATIC_QUIRKS */
  95};
  96
  97#ifdef ENABLE_AD_STATIC_QUIRKS
  98/*
  99 * input MUX handling (common part)
 100 */
 101static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 102{
 103        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 104        struct ad198x_spec *spec = codec->spec;
 105
 106        return snd_hda_input_mux_info(spec->input_mux, uinfo);
 107}
 108
 109static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 110{
 111        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 112        struct ad198x_spec *spec = codec->spec;
 113        unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 114
 115        ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
 116        return 0;
 117}
 118
 119static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 120{
 121        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 122        struct ad198x_spec *spec = codec->spec;
 123        unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 124
 125        return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
 126                                     spec->capsrc_nids[adc_idx],
 127                                     &spec->cur_mux[adc_idx]);
 128}
 129
 130/*
 131 * initialization (common callbacks)
 132 */
 133static int ad198x_init(struct hda_codec *codec)
 134{
 135        struct ad198x_spec *spec = codec->spec;
 136        int i;
 137
 138        for (i = 0; i < spec->num_init_verbs; i++)
 139                snd_hda_sequence_write(codec, spec->init_verbs[i]);
 140        return 0;
 141}
 142
 143static const char * const ad_slave_pfxs[] = {
 144        "Front", "Surround", "Center", "LFE", "Side",
 145        "Headphone", "Mono", "Speaker", "IEC958",
 146        NULL
 147};
 148
 149static const char * const ad1988_6stack_fp_slave_pfxs[] = {
 150        "Front", "Surround", "Center", "LFE", "Side", "IEC958",
 151        NULL
 152};
 153#endif /* ENABLE_AD_STATIC_QUIRKS */
 154
 155#ifdef CONFIG_SND_HDA_INPUT_BEEP
 156/* additional beep mixers; the actual parameters are overwritten at build */
 157static const struct snd_kcontrol_new ad_beep_mixer[] = {
 158        HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
 159        HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
 160        { } /* end */
 161};
 162
 163static const struct snd_kcontrol_new ad_beep2_mixer[] = {
 164        HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
 165        HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT),
 166        { } /* end */
 167};
 168
 169#define set_beep_amp(spec, nid, idx, dir) \
 170        ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
 171#else
 172#define set_beep_amp(spec, nid, idx, dir) /* NOP */
 173#endif
 174
 175#ifdef CONFIG_SND_HDA_INPUT_BEEP
 176static int create_beep_ctls(struct hda_codec *codec)
 177{
 178        struct ad198x_spec *spec = codec->spec;
 179        const struct snd_kcontrol_new *knew;
 180
 181        if (!spec->beep_amp)
 182                return 0;
 183
 184        knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
 185        for ( ; knew->name; knew++) {
 186                int err;
 187                struct snd_kcontrol *kctl;
 188                kctl = snd_ctl_new1(knew, codec);
 189                if (!kctl)
 190                        return -ENOMEM;
 191                kctl->private_value = spec->beep_amp;
 192                err = snd_hda_ctl_add(codec, 0, kctl);
 193                if (err < 0)
 194                        return err;
 195        }
 196        return 0;
 197}
 198#else
 199#define create_beep_ctls(codec)         0
 200#endif
 201
 202#ifdef ENABLE_AD_STATIC_QUIRKS
 203static int ad198x_build_controls(struct hda_codec *codec)
 204{
 205        struct ad198x_spec *spec = codec->spec;
 206        struct snd_kcontrol *kctl;
 207        unsigned int i;
 208        int err;
 209
 210        for (i = 0; i < spec->num_mixers; i++) {
 211                err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
 212                if (err < 0)
 213                        return err;
 214        }
 215        if (spec->multiout.dig_out_nid) {
 216                err = snd_hda_create_spdif_out_ctls(codec,
 217                                                    spec->multiout.dig_out_nid,
 218                                                    spec->multiout.dig_out_nid);
 219                if (err < 0)
 220                        return err;
 221                err = snd_hda_create_spdif_share_sw(codec,
 222                                                    &spec->multiout);
 223                if (err < 0)
 224                        return err;
 225                spec->multiout.share_spdif = 1;
 226        } 
 227        if (spec->dig_in_nid) {
 228                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
 229                if (err < 0)
 230                        return err;
 231        }
 232
 233        /* create beep controls if needed */
 234        err = create_beep_ctls(codec);
 235        if (err < 0)
 236                return err;
 237
 238        /* if we have no master control, let's create it */
 239        if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
 240                unsigned int vmaster_tlv[4];
 241                snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
 242                                        HDA_OUTPUT, vmaster_tlv);
 243                err = __snd_hda_add_vmaster(codec, "Master Playback Volume",
 244                                          vmaster_tlv,
 245                                          (spec->slave_vols ?
 246                                           spec->slave_vols : ad_slave_pfxs),
 247                                          "Playback Volume",
 248                                          !spec->avoid_init_slave_vol, NULL);
 249                if (err < 0)
 250                        return err;
 251        }
 252        if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
 253                err = snd_hda_add_vmaster(codec, "Master Playback Switch",
 254                                          NULL,
 255                                          (spec->slave_sws ?
 256                                           spec->slave_sws : ad_slave_pfxs),
 257                                          "Playback Switch");
 258                if (err < 0)
 259                        return err;
 260        }
 261
 262        /* assign Capture Source enums to NID */
 263        kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
 264        if (!kctl)
 265                kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
 266        for (i = 0; kctl && i < kctl->count; i++) {
 267                err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
 268                if (err < 0)
 269                        return err;
 270        }
 271
 272        /* assign IEC958 enums to NID */
 273        kctl = snd_hda_find_mixer_ctl(codec,
 274                        SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
 275        if (kctl) {
 276                err = snd_hda_add_nid(codec, kctl, 0,
 277                                      spec->multiout.dig_out_nid);
 278                if (err < 0)
 279                        return err;
 280        }
 281
 282        return 0;
 283}
 284
 285#ifdef CONFIG_PM
 286static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
 287{
 288        struct ad198x_spec *spec = codec->spec;
 289        return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
 290}
 291#endif
 292
 293/*
 294 * Analog playback callbacks
 295 */
 296static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
 297                                    struct hda_codec *codec,
 298                                    struct snd_pcm_substream *substream)
 299{
 300        struct ad198x_spec *spec = codec->spec;
 301        return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
 302                                             hinfo);
 303}
 304
 305static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 306                                       struct hda_codec *codec,
 307                                       unsigned int stream_tag,
 308                                       unsigned int format,
 309                                       struct snd_pcm_substream *substream)
 310{
 311        struct ad198x_spec *spec = codec->spec;
 312        return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
 313                                                format, substream);
 314}
 315
 316static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
 317                                       struct hda_codec *codec,
 318                                       struct snd_pcm_substream *substream)
 319{
 320        struct ad198x_spec *spec = codec->spec;
 321        return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
 322}
 323
 324/*
 325 * Digital out
 326 */
 327static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
 328                                        struct hda_codec *codec,
 329                                        struct snd_pcm_substream *substream)
 330{
 331        struct ad198x_spec *spec = codec->spec;
 332        return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 333}
 334
 335static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 336                                         struct hda_codec *codec,
 337                                         struct snd_pcm_substream *substream)
 338{
 339        struct ad198x_spec *spec = codec->spec;
 340        return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 341}
 342
 343static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 344                                           struct hda_codec *codec,
 345                                           unsigned int stream_tag,
 346                                           unsigned int format,
 347                                           struct snd_pcm_substream *substream)
 348{
 349        struct ad198x_spec *spec = codec->spec;
 350        return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
 351                                             format, substream);
 352}
 353
 354static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
 355                                           struct hda_codec *codec,
 356                                           struct snd_pcm_substream *substream)
 357{
 358        struct ad198x_spec *spec = codec->spec;
 359        return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
 360}
 361
 362/*
 363 * Analog capture
 364 */
 365static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
 366                                      struct hda_codec *codec,
 367                                      unsigned int stream_tag,
 368                                      unsigned int format,
 369                                      struct snd_pcm_substream *substream)
 370{
 371        struct ad198x_spec *spec = codec->spec;
 372        snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
 373                                   stream_tag, 0, format);
 374        return 0;
 375}
 376
 377static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 378                                      struct hda_codec *codec,
 379                                      struct snd_pcm_substream *substream)
 380{
 381        struct ad198x_spec *spec = codec->spec;
 382        snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 383        return 0;
 384}
 385
 386/*
 387 */
 388static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
 389        .substreams = 1,
 390        .channels_min = 2,
 391        .channels_max = 6, /* changed later */
 392        .nid = 0, /* fill later */
 393        .ops = {
 394                .open = ad198x_playback_pcm_open,
 395                .prepare = ad198x_playback_pcm_prepare,
 396                .cleanup = ad198x_playback_pcm_cleanup,
 397        },
 398};
 399
 400static const struct hda_pcm_stream ad198x_pcm_analog_capture = {
 401        .substreams = 1,
 402        .channels_min = 2,
 403        .channels_max = 2,
 404        .nid = 0, /* fill later */
 405        .ops = {
 406                .prepare = ad198x_capture_pcm_prepare,
 407                .cleanup = ad198x_capture_pcm_cleanup
 408        },
 409};
 410
 411static const struct hda_pcm_stream ad198x_pcm_digital_playback = {
 412        .substreams = 1,
 413        .channels_min = 2,
 414        .channels_max = 2,
 415        .nid = 0, /* fill later */
 416        .ops = {
 417                .open = ad198x_dig_playback_pcm_open,
 418                .close = ad198x_dig_playback_pcm_close,
 419                .prepare = ad198x_dig_playback_pcm_prepare,
 420                .cleanup = ad198x_dig_playback_pcm_cleanup
 421        },
 422};
 423
 424static const struct hda_pcm_stream ad198x_pcm_digital_capture = {
 425        .substreams = 1,
 426        .channels_min = 2,
 427        .channels_max = 2,
 428        /* NID is set in alc_build_pcms */
 429};
 430
 431static int ad198x_build_pcms(struct hda_codec *codec)
 432{
 433        struct ad198x_spec *spec = codec->spec;
 434        struct hda_pcm *info = spec->pcm_rec;
 435
 436        codec->num_pcms = 1;
 437        codec->pcm_info = info;
 438
 439        info->name = "AD198x Analog";
 440        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
 441        info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
 442        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
 443        info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
 444        info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
 445        info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
 446
 447        if (spec->multiout.dig_out_nid) {
 448                info++;
 449                codec->num_pcms++;
 450                codec->spdif_status_reset = 1;
 451                info->name = "AD198x Digital";
 452                info->pcm_type = HDA_PCM_TYPE_SPDIF;
 453                info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
 454                info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
 455                if (spec->dig_in_nid) {
 456                        info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
 457                        info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
 458                }
 459        }
 460
 461        return 0;
 462}
 463#endif /* ENABLE_AD_STATIC_QUIRKS */
 464
 465static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
 466                                hda_nid_t hp)
 467{
 468        if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
 469                snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
 470                            !codec->inv_eapd ? 0x00 : 0x02);
 471        if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
 472                snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
 473                            !codec->inv_eapd ? 0x00 : 0x02);
 474}
 475
 476static void ad198x_power_eapd(struct hda_codec *codec)
 477{
 478        /* We currently only handle front, HP */
 479        switch (codec->vendor_id) {
 480        case 0x11d41882:
 481        case 0x11d4882a:
 482        case 0x11d41884:
 483        case 0x11d41984:
 484        case 0x11d41883:
 485        case 0x11d4184a:
 486        case 0x11d4194a:
 487        case 0x11d4194b:
 488        case 0x11d41988:
 489        case 0x11d4198b:
 490        case 0x11d4989a:
 491        case 0x11d4989b:
 492                ad198x_power_eapd_write(codec, 0x12, 0x11);
 493                break;
 494        case 0x11d41981:
 495        case 0x11d41983:
 496                ad198x_power_eapd_write(codec, 0x05, 0x06);
 497                break;
 498        case 0x11d41986:
 499                ad198x_power_eapd_write(codec, 0x1b, 0x1a);
 500                break;
 501        }
 502}
 503
 504static void ad198x_shutup(struct hda_codec *codec)
 505{
 506        snd_hda_shutup_pins(codec);
 507        ad198x_power_eapd(codec);
 508}
 509
 510static void ad198x_free(struct hda_codec *codec)
 511{
 512        struct ad198x_spec *spec = codec->spec;
 513
 514        if (!spec)
 515                return;
 516
 517        snd_hda_gen_spec_free(&spec->gen);
 518        kfree(spec);
 519        snd_hda_detach_beep_device(codec);
 520}
 521
 522#ifdef CONFIG_PM
 523static int ad198x_suspend(struct hda_codec *codec)
 524{
 525        ad198x_shutup(codec);
 526        return 0;
 527}
 528#endif
 529
 530#ifdef ENABLE_AD_STATIC_QUIRKS
 531static const struct hda_codec_ops ad198x_patch_ops = {
 532        .build_controls = ad198x_build_controls,
 533        .build_pcms = ad198x_build_pcms,
 534        .init = ad198x_init,
 535        .free = ad198x_free,
 536#ifdef CONFIG_PM
 537        .check_power_status = ad198x_check_power_status,
 538        .suspend = ad198x_suspend,
 539#endif
 540        .reboot_notify = ad198x_shutup,
 541};
 542
 543
 544/*
 545 * EAPD control
 546 * the private value = nid
 547 */
 548#define ad198x_eapd_info        snd_ctl_boolean_mono_info
 549
 550static int ad198x_eapd_get(struct snd_kcontrol *kcontrol,
 551                           struct snd_ctl_elem_value *ucontrol)
 552{
 553        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 554        struct ad198x_spec *spec = codec->spec;
 555        if (codec->inv_eapd)
 556                ucontrol->value.integer.value[0] = ! spec->cur_eapd;
 557        else
 558                ucontrol->value.integer.value[0] = spec->cur_eapd;
 559        return 0;
 560}
 561
 562static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
 563                           struct snd_ctl_elem_value *ucontrol)
 564{
 565        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 566        struct ad198x_spec *spec = codec->spec;
 567        hda_nid_t nid = kcontrol->private_value & 0xff;
 568        unsigned int eapd;
 569        eapd = !!ucontrol->value.integer.value[0];
 570        if (codec->inv_eapd)
 571                eapd = !eapd;
 572        if (eapd == spec->cur_eapd)
 573                return 0;
 574        spec->cur_eapd = eapd;
 575        snd_hda_codec_write_cache(codec, nid,
 576                                  0, AC_VERB_SET_EAPD_BTLENABLE,
 577                                  eapd ? 0x02 : 0x00);
 578        return 1;
 579}
 580
 581static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
 582                               struct snd_ctl_elem_info *uinfo);
 583static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
 584                              struct snd_ctl_elem_value *ucontrol);
 585static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
 586                              struct snd_ctl_elem_value *ucontrol);
 587#endif /* ENABLE_AD_STATIC_QUIRKS */
 588
 589
 590/*
 591 * Automatic parse of I/O pins from the BIOS configuration
 592 */
 593
 594static int ad198x_auto_build_controls(struct hda_codec *codec)
 595{
 596        int err;
 597
 598        err = snd_hda_gen_build_controls(codec);
 599        if (err < 0)
 600                return err;
 601        err = create_beep_ctls(codec);
 602        if (err < 0)
 603                return err;
 604        return 0;
 605}
 606
 607static const struct hda_codec_ops ad198x_auto_patch_ops = {
 608        .build_controls = ad198x_auto_build_controls,
 609        .build_pcms = snd_hda_gen_build_pcms,
 610        .init = snd_hda_gen_init,
 611        .free = snd_hda_gen_free,
 612        .unsol_event = snd_hda_jack_unsol_event,
 613#ifdef CONFIG_PM
 614        .check_power_status = snd_hda_gen_check_power_status,
 615        .suspend = ad198x_suspend,
 616#endif
 617        .reboot_notify = ad198x_shutup,
 618};
 619
 620
 621static int ad198x_parse_auto_config(struct hda_codec *codec)
 622{
 623        struct ad198x_spec *spec = codec->spec;
 624        struct auto_pin_cfg *cfg = &spec->gen.autocfg;
 625        int err;
 626
 627        codec->spdif_status_reset = 1;
 628        codec->no_trigger_sense = 1;
 629        codec->no_sticky_stream = 1;
 630
 631        spec->gen.indep_hp = 1;
 632
 633        err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
 634        if (err < 0)
 635                return err;
 636        err = snd_hda_gen_parse_auto_config(codec, cfg);
 637        if (err < 0)
 638                return err;
 639
 640        codec->patch_ops = ad198x_auto_patch_ops;
 641
 642        return 0;
 643}
 644
 645/*
 646 * AD1986A specific
 647 */
 648
 649#ifdef ENABLE_AD_STATIC_QUIRKS
 650#define AD1986A_SPDIF_OUT       0x02
 651#define AD1986A_FRONT_DAC       0x03
 652#define AD1986A_SURR_DAC        0x04
 653#define AD1986A_CLFE_DAC        0x05
 654#define AD1986A_ADC             0x06
 655
 656static const hda_nid_t ad1986a_dac_nids[3] = {
 657        AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
 658};
 659static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
 660static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
 661
 662static const struct hda_input_mux ad1986a_capture_source = {
 663        .num_items = 7,
 664        .items = {
 665                { "Mic", 0x0 },
 666                { "CD", 0x1 },
 667                { "Aux", 0x3 },
 668                { "Line", 0x4 },
 669                { "Mix", 0x5 },
 670                { "Mono", 0x6 },
 671                { "Phone", 0x7 },
 672        },
 673};
 674
 675
 676static const struct hda_bind_ctls ad1986a_bind_pcm_vol = {
 677        .ops = &snd_hda_bind_vol,
 678        .values = {
 679                HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
 680                HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
 681                HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
 682                0
 683        },
 684};
 685
 686static const struct hda_bind_ctls ad1986a_bind_pcm_sw = {
 687        .ops = &snd_hda_bind_sw,
 688        .values = {
 689                HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
 690                HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
 691                HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
 692                0
 693        },
 694};
 695
 696/*
 697 * mixers
 698 */
 699static const struct snd_kcontrol_new ad1986a_mixers[] = {
 700        /*
 701         * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
 702         */
 703        HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
 704        HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
 705        HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
 706        HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 707        HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
 708        HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
 709        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
 710        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
 711        HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
 712        HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
 713        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
 714        HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
 715        HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
 716        HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
 717        HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
 718        HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
 719        HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
 720        HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
 721        HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
 722        HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
 723        HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
 724        HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
 725        HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
 726        HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
 727        HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
 728        {
 729                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 730                .name = "Capture Source",
 731                .info = ad198x_mux_enum_info,
 732                .get = ad198x_mux_enum_get,
 733                .put = ad198x_mux_enum_put,
 734        },
 735        HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
 736        { } /* end */
 737};
 738
 739/* additional mixers for 3stack mode */
 740static const struct snd_kcontrol_new ad1986a_3st_mixers[] = {
 741        {
 742                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 743                .name = "Channel Mode",
 744                .info = ad198x_ch_mode_info,
 745                .get = ad198x_ch_mode_get,
 746                .put = ad198x_ch_mode_put,
 747        },
 748        { } /* end */
 749};
 750
 751/* laptop model - 2ch only */
 752static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
 753
 754/* master controls both pins 0x1a and 0x1b */
 755static const struct hda_bind_ctls ad1986a_laptop_master_vol = {
 756        .ops = &snd_hda_bind_vol,
 757        .values = {
 758                HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
 759                HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
 760                0,
 761        },
 762};
 763
 764static const struct hda_bind_ctls ad1986a_laptop_master_sw = {
 765        .ops = &snd_hda_bind_sw,
 766        .values = {
 767                HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
 768                HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
 769                0,
 770        },
 771};
 772
 773static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
 774        HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
 775        HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
 776        HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
 777        HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
 778        HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
 779        HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
 780        HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
 781        HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
 782        HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
 783        HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
 784        HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
 785        HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
 786        HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
 787        /* 
 788           HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
 789           HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */
 790        HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
 791        HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
 792        {
 793                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 794                .name = "Capture Source",
 795                .info = ad198x_mux_enum_info,
 796                .get = ad198x_mux_enum_get,
 797                .put = ad198x_mux_enum_put,
 798        },
 799        { } /* end */
 800};
 801
 802/* laptop-eapd model - 2ch only */
 803
 804static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
 805        .num_items = 3,
 806        .items = {
 807                { "Mic", 0x0 },
 808                { "Internal Mic", 0x4 },
 809                { "Mix", 0x5 },
 810        },
 811};
 812
 813static const struct hda_input_mux ad1986a_automic_capture_source = {
 814        .num_items = 2,
 815        .items = {
 816                { "Mic", 0x0 },
 817                { "Mix", 0x5 },
 818        },
 819};
 820
 821static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
 822        HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
 823        HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
 824        { } /* end */
 825};
 826
 827static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
 828        HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
 829        HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
 830        HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
 831        HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
 832        HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT),
 833        HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
 834        HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
 835        {
 836                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 837                .name = "Capture Source",
 838                .info = ad198x_mux_enum_info,
 839                .get = ad198x_mux_enum_get,
 840                .put = ad198x_mux_enum_put,
 841        },
 842        {
 843                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 844                .name = "External Amplifier",
 845                .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
 846                .info = ad198x_eapd_info,
 847                .get = ad198x_eapd_get,
 848                .put = ad198x_eapd_put,
 849                .private_value = 0x1b, /* port-D */
 850        },
 851        { } /* end */
 852};
 853
 854static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
 855        HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
 856        HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
 857        { } /* end */
 858};
 859
 860/* re-connect the mic boost input according to the jack sensing */
 861static void ad1986a_automic(struct hda_codec *codec)
 862{
 863        unsigned int present;
 864        present = snd_hda_jack_detect(codec, 0x1f);
 865        /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
 866        snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
 867                            present ? 0 : 2);
 868}
 869
 870#define AD1986A_MIC_EVENT               0x36
 871
 872static void ad1986a_automic_unsol_event(struct hda_codec *codec,
 873                                            unsigned int res)
 874{
 875        if ((res >> 26) != AD1986A_MIC_EVENT)
 876                return;
 877        ad1986a_automic(codec);
 878}
 879
 880static int ad1986a_automic_init(struct hda_codec *codec)
 881{
 882        ad198x_init(codec);
 883        ad1986a_automic(codec);
 884        return 0;
 885}
 886
 887/* laptop-automute - 2ch only */
 888
 889static void ad1986a_update_hp(struct hda_codec *codec)
 890{
 891        struct ad198x_spec *spec = codec->spec;
 892        unsigned int mute;
 893
 894        if (spec->jack_present)
 895                mute = HDA_AMP_MUTE; /* mute internal speaker */
 896        else
 897                /* unmute internal speaker if necessary */
 898                mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0);
 899        snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
 900                                 HDA_AMP_MUTE, mute);
 901}
 902
 903static void ad1986a_hp_automute(struct hda_codec *codec)
 904{
 905        struct ad198x_spec *spec = codec->spec;
 906
 907        spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
 908        if (spec->inv_jack_detect)
 909                spec->jack_present = !spec->jack_present;
 910        ad1986a_update_hp(codec);
 911}
 912
 913#define AD1986A_HP_EVENT                0x37
 914
 915static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
 916{
 917        if ((res >> 26) != AD1986A_HP_EVENT)
 918                return;
 919        ad1986a_hp_automute(codec);
 920}
 921
 922static int ad1986a_hp_init(struct hda_codec *codec)
 923{
 924        ad198x_init(codec);
 925        ad1986a_hp_automute(codec);
 926        return 0;
 927}
 928
 929/* bind hp and internal speaker mute (with plug check) */
 930static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 931                                    struct snd_ctl_elem_value *ucontrol)
 932{
 933        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 934        int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
 935        if (change)
 936                ad1986a_update_hp(codec);
 937        return change;
 938}
 939
 940static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
 941        HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
 942        {
 943                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 944                .name = "Master Playback Switch",
 945                .subdevice = HDA_SUBDEV_AMP_FLAG,
 946                .info = snd_hda_mixer_amp_switch_info,
 947                .get = snd_hda_mixer_amp_switch_get,
 948                .put = ad1986a_hp_master_sw_put,
 949                .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
 950        },
 951        { } /* end */
 952};
 953
 954
 955/*
 956 * initialization verbs
 957 */
 958static const struct hda_verb ad1986a_init_verbs[] = {
 959        /* Front, Surround, CLFE DAC; mute as default */
 960        {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 961        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 962        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 963        /* Downmix - off */
 964        {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 965        /* HP, Line-Out, Surround, CLFE selectors */
 966        {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
 967        {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
 968        {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
 969        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
 970        /* Mono selector */
 971        {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
 972        /* Mic selector: Mic 1/2 pin */
 973        {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
 974        /* Line-in selector: Line-in */
 975        {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
 976        /* Mic 1/2 swap */
 977        {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
 978        /* Record selector: mic */
 979        {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
 980        /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
 981        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 982        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 983        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 984        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 985        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 986        /* PC beep */
 987        {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
 988        /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
 989        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 990        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 991        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 992        {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 993        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 994        /* HP Pin */
 995        {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
 996        /* Front, Surround, CLFE Pins */
 997        {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 998        {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 999        {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1000        /* Mono Pin */
1001        {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1002        /* Mic Pin */
1003        {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1004        /* Line, Aux, CD, Beep-In Pin */
1005        {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1006        {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1007        {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1008        {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1009        {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1010        { } /* end */
1011};
1012
1013static const struct hda_verb ad1986a_ch2_init[] = {
1014        /* Surround out -> Line In */
1015        { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1016        /* Line-in selectors */
1017        { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
1018        /* CLFE -> Mic in */
1019        { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1020        /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
1021        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1022        { } /* end */
1023};
1024
1025static const struct hda_verb ad1986a_ch4_init[] = {
1026        /* Surround out -> Surround */
1027        { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1028        { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1029        /* CLFE -> Mic in */
1030        { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1031        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
1032        { } /* end */
1033};
1034
1035static const struct hda_verb ad1986a_ch6_init[] = {
1036        /* Surround out -> Surround out */
1037        { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1038        { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1039        /* CLFE -> CLFE */
1040        { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1041        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
1042        { } /* end */
1043};
1044
1045static const struct hda_channel_mode ad1986a_modes[3] = {
1046        { 2, ad1986a_ch2_init },
1047        { 4, ad1986a_ch4_init },
1048        { 6, ad1986a_ch6_init },
1049};
1050
1051/* eapd initialization */
1052static const struct hda_verb ad1986a_eapd_init_verbs[] = {
1053        {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1054        {}
1055};
1056
1057static const struct hda_verb ad1986a_automic_verbs[] = {
1058        {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1059        {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1060        /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
1061        {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
1062        {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
1063        {}
1064};
1065
1066/* Ultra initialization */
1067static const struct hda_verb ad1986a_ultra_init[] = {
1068        /* eapd initialization */
1069        { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
1070        /* CLFE -> Mic in */
1071        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
1072        { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1073        { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
1074        { } /* end */
1075};
1076
1077/* pin sensing on HP jack */
1078static const struct hda_verb ad1986a_hp_init_verbs[] = {
1079        {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
1080        {}
1081};
1082
1083static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
1084                                            unsigned int res)
1085{
1086        switch (res >> 26) {
1087        case AD1986A_HP_EVENT:
1088                ad1986a_hp_automute(codec);
1089                break;
1090        case AD1986A_MIC_EVENT:
1091                ad1986a_automic(codec);
1092                break;
1093        }
1094}
1095
1096static int ad1986a_samsung_p50_init(struct hda_codec *codec)
1097{
1098        ad198x_init(codec);
1099        ad1986a_hp_automute(codec);
1100        ad1986a_automic(codec);
1101        return 0;
1102}
1103
1104
1105/* models */
1106enum {
1107        AD1986A_AUTO,
1108        AD1986A_6STACK,
1109        AD1986A_3STACK,
1110        AD1986A_LAPTOP,
1111        AD1986A_LAPTOP_EAPD,
1112        AD1986A_LAPTOP_AUTOMUTE,
1113        AD1986A_ULTRA,
1114        AD1986A_SAMSUNG,
1115        AD1986A_SAMSUNG_P50,
1116        AD1986A_MODELS
1117};
1118
1119static const char * const ad1986a_models[AD1986A_MODELS] = {
1120        [AD1986A_AUTO]          = "auto",
1121        [AD1986A_6STACK]        = "6stack",
1122        [AD1986A_3STACK]        = "3stack",
1123        [AD1986A_LAPTOP]        = "laptop",
1124        [AD1986A_LAPTOP_EAPD]   = "laptop-eapd",
1125        [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
1126        [AD1986A_ULTRA]         = "ultra",
1127        [AD1986A_SAMSUNG]       = "samsung",
1128        [AD1986A_SAMSUNG_P50]   = "samsung-p50",
1129};
1130
1131static const struct snd_pci_quirk ad1986a_cfg_tbl[] = {
1132        SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
1133        SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
1134        SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
1135        SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
1136        SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
1137        SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
1138        SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
1139        SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
1140        SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP),
1141        SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
1142        SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
1143        SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
1144        SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
1145        SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
1146        SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
1147        SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
1148        SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
1149        SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
1150        SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
1151        SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
1152        SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
1153        SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
1154        SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
1155        SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
1156        SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
1157        SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE),
1158        SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
1159        {}
1160};
1161
1162#ifdef CONFIG_PM
1163static const struct hda_amp_list ad1986a_loopbacks[] = {
1164        { 0x13, HDA_OUTPUT, 0 }, /* Mic */
1165        { 0x14, HDA_OUTPUT, 0 }, /* Phone */
1166        { 0x15, HDA_OUTPUT, 0 }, /* CD */
1167        { 0x16, HDA_OUTPUT, 0 }, /* Aux */
1168        { 0x17, HDA_OUTPUT, 0 }, /* Line */
1169        { } /* end */
1170};
1171#endif
1172
1173static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
1174{
1175        unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
1176        return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
1177}
1178#endif /* ENABLE_AD_STATIC_QUIRKS */
1179
1180static int alloc_ad_spec(struct hda_codec *codec)
1181{
1182        struct ad198x_spec *spec;
1183
1184        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1185        if (!spec)
1186                return -ENOMEM;
1187        codec->spec = spec;
1188        snd_hda_gen_spec_init(&spec->gen);
1189        return 0;
1190}
1191
1192/*
1193 * AD1986A fixup codes
1194 */
1195
1196/* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
1197static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
1198                                     const struct hda_fixup *fix, int action)
1199{
1200        if (action == HDA_FIXUP_ACT_PRE_PROBE)
1201                codec->inv_jack_detect = 1;
1202}
1203
1204enum {
1205        AD1986A_FIXUP_INV_JACK_DETECT,
1206};
1207
1208static const struct hda_fixup ad1986a_fixups[] = {
1209        [AD1986A_FIXUP_INV_JACK_DETECT] = {
1210                .type = HDA_FIXUP_FUNC,
1211                .v.func = ad_fixup_inv_jack_detect,
1212        },
1213};
1214
1215static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
1216        SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT),
1217        {}
1218};
1219
1220/*
1221 */
1222static int ad1986a_parse_auto_config(struct hda_codec *codec)
1223{
1224        int err;
1225        struct ad198x_spec *spec;
1226
1227        err = alloc_ad_spec(codec);
1228        if (err < 0)
1229                return err;
1230        spec = codec->spec;
1231
1232        /* AD1986A has the inverted EAPD implementation */
1233        codec->inv_eapd = 1;
1234
1235        spec->gen.mixer_nid = 0x07;
1236        spec->gen.beep_nid = 0x19;
1237        set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1238
1239        /* AD1986A has a hardware problem that it can't share a stream
1240         * with multiple output pins.  The copy of front to surrounds
1241         * causes noisy or silent outputs at a certain timing, e.g.
1242         * changing the volume.
1243         * So, let's disable the shared stream.
1244         */
1245        spec->gen.multiout.no_share_stream = 1;
1246
1247        snd_hda_pick_fixup(codec, NULL, ad1986a_fixup_tbl, ad1986a_fixups);
1248        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1249
1250        err = ad198x_parse_auto_config(codec);
1251        if (err < 0) {
1252                snd_hda_gen_free(codec);
1253                return err;
1254        }
1255
1256        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
1257
1258        return 0;
1259}
1260
1261#ifdef ENABLE_AD_STATIC_QUIRKS
1262static int patch_ad1986a(struct hda_codec *codec)
1263{
1264        struct ad198x_spec *spec;
1265        int err, board_config;
1266
1267        board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
1268                                                  ad1986a_models,
1269                                                  ad1986a_cfg_tbl);
1270        if (board_config < 0) {
1271                printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
1272                       codec->chip_name);
1273                board_config = AD1986A_AUTO;
1274        }
1275
1276        if (board_config == AD1986A_AUTO)
1277                return ad1986a_parse_auto_config(codec);
1278
1279        err = alloc_ad_spec(codec);
1280        if (err < 0)
1281                return err;
1282        spec = codec->spec;
1283
1284        err = snd_hda_attach_beep_device(codec, 0x19);
1285        if (err < 0) {
1286                ad198x_free(codec);
1287                return err;
1288        }
1289        set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
1290
1291        spec->multiout.max_channels = 6;
1292        spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
1293        spec->multiout.dac_nids = ad1986a_dac_nids;
1294        spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
1295        spec->num_adc_nids = 1;
1296        spec->adc_nids = ad1986a_adc_nids;
1297        spec->capsrc_nids = ad1986a_capsrc_nids;
1298        spec->input_mux = &ad1986a_capture_source;
1299        spec->num_mixers = 1;
1300        spec->mixers[0] = ad1986a_mixers;
1301        spec->num_init_verbs = 1;
1302        spec->init_verbs[0] = ad1986a_init_verbs;
1303#ifdef CONFIG_PM
1304        spec->loopback.amplist = ad1986a_loopbacks;
1305#endif
1306        spec->vmaster_nid = 0x1b;
1307        codec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */
1308
1309        codec->patch_ops = ad198x_patch_ops;
1310
1311        /* override some parameters */
1312        switch (board_config) {
1313        case AD1986A_3STACK:
1314                spec->num_mixers = 2;
1315                spec->mixers[1] = ad1986a_3st_mixers;
1316                spec->num_init_verbs = 2;
1317                spec->init_verbs[1] = ad1986a_ch2_init;
1318                spec->channel_mode = ad1986a_modes;
1319                spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
1320                spec->need_dac_fix = 1;
1321                spec->multiout.max_channels = 2;
1322                spec->multiout.num_dacs = 1;
1323                break;
1324        case AD1986A_LAPTOP:
1325                spec->mixers[0] = ad1986a_laptop_mixers;
1326                spec->multiout.max_channels = 2;
1327                spec->multiout.num_dacs = 1;
1328                spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1329                break;
1330        case AD1986A_LAPTOP_EAPD:
1331                spec->num_mixers = 3;
1332                spec->mixers[0] = ad1986a_laptop_master_mixers;
1333                spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1334                spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1335                spec->num_init_verbs = 2;
1336                spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1337                spec->multiout.max_channels = 2;
1338                spec->multiout.num_dacs = 1;
1339                spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1340                if (!is_jack_available(codec, 0x25))
1341                        spec->multiout.dig_out_nid = 0;
1342                spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1343                break;
1344        case AD1986A_SAMSUNG:
1345                spec->num_mixers = 2;
1346                spec->mixers[0] = ad1986a_laptop_master_mixers;
1347                spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1348                spec->num_init_verbs = 3;
1349                spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1350                spec->init_verbs[2] = ad1986a_automic_verbs;
1351                spec->multiout.max_channels = 2;
1352                spec->multiout.num_dacs = 1;
1353                spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1354                if (!is_jack_available(codec, 0x25))
1355                        spec->multiout.dig_out_nid = 0;
1356                spec->input_mux = &ad1986a_automic_capture_source;
1357                codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
1358                codec->patch_ops.init = ad1986a_automic_init;
1359                break;
1360        case AD1986A_SAMSUNG_P50:
1361                spec->num_mixers = 2;
1362                spec->mixers[0] = ad1986a_automute_master_mixers;
1363                spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1364                spec->num_init_verbs = 4;
1365                spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1366                spec->init_verbs[2] = ad1986a_automic_verbs;
1367                spec->init_verbs[3] = ad1986a_hp_init_verbs;
1368                spec->multiout.max_channels = 2;
1369                spec->multiout.num_dacs = 1;
1370                spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1371                if (!is_jack_available(codec, 0x25))
1372                        spec->multiout.dig_out_nid = 0;
1373                spec->input_mux = &ad1986a_automic_capture_source;
1374                codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
1375                codec->patch_ops.init = ad1986a_samsung_p50_init;
1376                break;
1377        case AD1986A_LAPTOP_AUTOMUTE:
1378                spec->num_mixers = 3;
1379                spec->mixers[0] = ad1986a_automute_master_mixers;
1380                spec->mixers[1] = ad1986a_laptop_eapd_mixers;
1381                spec->mixers[2] = ad1986a_laptop_intmic_mixers;
1382                spec->num_init_verbs = 3;
1383                spec->init_verbs[1] = ad1986a_eapd_init_verbs;
1384                spec->init_verbs[2] = ad1986a_hp_init_verbs;
1385                spec->multiout.max_channels = 2;
1386                spec->multiout.num_dacs = 1;
1387                spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1388                if (!is_jack_available(codec, 0x25))
1389                        spec->multiout.dig_out_nid = 0;
1390                spec->input_mux = &ad1986a_laptop_eapd_capture_source;
1391                codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
1392                codec->patch_ops.init = ad1986a_hp_init;
1393                /* Lenovo N100 seems to report the reversed bit
1394                 * for HP jack-sensing
1395                 */
1396                spec->inv_jack_detect = 1;
1397                break;
1398        case AD1986A_ULTRA:
1399                spec->mixers[0] = ad1986a_laptop_eapd_mixers;
1400                spec->num_init_verbs = 2;
1401                spec->init_verbs[1] = ad1986a_ultra_init;
1402                spec->multiout.max_channels = 2;
1403                spec->multiout.num_dacs = 1;
1404                spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
1405                spec->multiout.dig_out_nid = 0;
1406                break;
1407        }
1408
1409        /* AD1986A has a hardware problem that it can't share a stream
1410         * with multiple output pins.  The copy of front to surrounds
1411         * causes noisy or silent outputs at a certain timing, e.g.
1412         * changing the volume.
1413         * So, let's disable the shared stream.
1414         */
1415        spec->multiout.no_share_stream = 1;
1416
1417        codec->no_trigger_sense = 1;
1418        codec->no_sticky_stream = 1;
1419
1420        return 0;
1421}
1422#else /* ENABLE_AD_STATIC_QUIRKS */
1423#define patch_ad1986a   ad1986a_parse_auto_config
1424#endif /* ENABLE_AD_STATIC_QUIRKS */
1425
1426/*
1427 * AD1983 specific
1428 */
1429
1430#ifdef ENABLE_AD_STATIC_QUIRKS
1431#define AD1983_SPDIF_OUT        0x02
1432#define AD1983_DAC              0x03
1433#define AD1983_ADC              0x04
1434
1435static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
1436static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
1437static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
1438
1439static const struct hda_input_mux ad1983_capture_source = {
1440        .num_items = 4,
1441        .items = {
1442                { "Mic", 0x0 },
1443                { "Line", 0x1 },
1444                { "Mix", 0x2 },
1445                { "Mix Mono", 0x3 },
1446        },
1447};
1448
1449/*
1450 * SPDIF playback route
1451 */
1452static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1453{
1454        static const char * const texts[] = { "PCM", "ADC" };
1455
1456        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1457        uinfo->count = 1;
1458        uinfo->value.enumerated.items = 2;
1459        if (uinfo->value.enumerated.item > 1)
1460                uinfo->value.enumerated.item = 1;
1461        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1462        return 0;
1463}
1464
1465static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1466{
1467        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1468        struct ad198x_spec *spec = codec->spec;
1469
1470        ucontrol->value.enumerated.item[0] = spec->spdif_route;
1471        return 0;
1472}
1473
1474static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1475{
1476        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1477        struct ad198x_spec *spec = codec->spec;
1478
1479        if (ucontrol->value.enumerated.item[0] > 1)
1480                return -EINVAL;
1481        if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1482                spec->spdif_route = ucontrol->value.enumerated.item[0];
1483                snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
1484                                          AC_VERB_SET_CONNECT_SEL,
1485                                          spec->spdif_route);
1486                return 1;
1487        }
1488        return 0;
1489}
1490
1491static const struct snd_kcontrol_new ad1983_mixers[] = {
1492        HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1493        HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1494        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1495        HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1496        HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1497        HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1498        HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1499        HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1500        HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1501        HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1502        HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1503        HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1504        HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT),
1505        HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1506        HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1507        {
1508                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509                .name = "Capture Source",
1510                .info = ad198x_mux_enum_info,
1511                .get = ad198x_mux_enum_get,
1512                .put = ad198x_mux_enum_put,
1513        },
1514        {
1515                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1516                .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1517                .info = ad1983_spdif_route_info,
1518                .get = ad1983_spdif_route_get,
1519                .put = ad1983_spdif_route_put,
1520        },
1521        { } /* end */
1522};
1523
1524static const struct hda_verb ad1983_init_verbs[] = {
1525        /* Front, HP, Mono; mute as default */
1526        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1527        {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1528        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1529        /* Beep, PCM, Mic, Line-In: mute */
1530        {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1531        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1532        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1533        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1534        /* Front, HP selectors; from Mix */
1535        {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1536        {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1537        /* Mono selector; from Mix */
1538        {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1539        /* Mic selector; Mic */
1540        {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
1541        /* Line-in selector: Line-in */
1542        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
1543        /* Mic boost: 0dB */
1544        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1545        /* Record selector: mic */
1546        {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1547        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1548        /* SPDIF route: PCM */
1549        {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1550        /* Front Pin */
1551        {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1552        /* HP Pin */
1553        {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1554        /* Mono Pin */
1555        {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1556        /* Mic Pin */
1557        {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1558        /* Line Pin */
1559        {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1560        { } /* end */
1561};
1562
1563#ifdef CONFIG_PM
1564static const struct hda_amp_list ad1983_loopbacks[] = {
1565        { 0x12, HDA_OUTPUT, 0 }, /* Mic */
1566        { 0x13, HDA_OUTPUT, 0 }, /* Line */
1567        { } /* end */
1568};
1569#endif
1570
1571/* models */
1572enum {
1573        AD1983_AUTO,
1574        AD1983_BASIC,
1575        AD1983_MODELS
1576};
1577
1578static const char * const ad1983_models[AD1983_MODELS] = {
1579        [AD1983_AUTO]           = "auto",
1580        [AD1983_BASIC]          = "basic",
1581};
1582#endif /* ENABLE_AD_STATIC_QUIRKS */
1583
1584
1585/*
1586 * SPDIF mux control for AD1983 auto-parser
1587 */
1588static int ad1983_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
1589                                      struct snd_ctl_elem_info *uinfo)
1590{
1591        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1592        struct ad198x_spec *spec = codec->spec;
1593        static const char * const texts2[] = { "PCM", "ADC" };
1594        static const char * const texts3[] = { "PCM", "ADC1", "ADC2" };
1595        hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1596        int num_conns = snd_hda_get_num_conns(codec, dig_out);
1597
1598        if (num_conns == 2)
1599                return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts2);
1600        else if (num_conns == 3)
1601                return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
1602        else
1603                return -EINVAL;
1604}
1605
1606static int ad1983_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
1607                                     struct snd_ctl_elem_value *ucontrol)
1608{
1609        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1610        struct ad198x_spec *spec = codec->spec;
1611
1612        ucontrol->value.enumerated.item[0] = spec->cur_smux;
1613        return 0;
1614}
1615
1616static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
1617                                     struct snd_ctl_elem_value *ucontrol)
1618{
1619        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1620        struct ad198x_spec *spec = codec->spec;
1621        unsigned int val = ucontrol->value.enumerated.item[0];
1622        hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1623        int num_conns = snd_hda_get_num_conns(codec, dig_out);
1624
1625        if (val >= num_conns)
1626                return -EINVAL;
1627        if (spec->cur_smux == val)
1628                return 0;
1629        spec->cur_smux = val;
1630        snd_hda_codec_write_cache(codec, dig_out, 0,
1631                                  AC_VERB_SET_CONNECT_SEL, val);
1632        return 1;
1633}
1634
1635static struct snd_kcontrol_new ad1983_auto_smux_mixer = {
1636        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1637        .name = "IEC958 Playback Source",
1638        .info = ad1983_auto_smux_enum_info,
1639        .get = ad1983_auto_smux_enum_get,
1640        .put = ad1983_auto_smux_enum_put,
1641};
1642
1643static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
1644{
1645        struct ad198x_spec *spec = codec->spec;
1646        hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1647        int num_conns;
1648
1649        if (!dig_out)
1650                return 0;
1651        num_conns = snd_hda_get_num_conns(codec, dig_out);
1652        if (num_conns != 2 && num_conns != 3)
1653                return 0;
1654        if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1983_auto_smux_mixer))
1655                return -ENOMEM;
1656        return 0;
1657}
1658
1659static int ad1983_parse_auto_config(struct hda_codec *codec)
1660{
1661        struct ad198x_spec *spec;
1662        int err;
1663
1664        err = alloc_ad_spec(codec);
1665        if (err < 0)
1666                return err;
1667        spec = codec->spec;
1668
1669        spec->gen.beep_nid = 0x10;
1670        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1671        err = ad198x_parse_auto_config(codec);
1672        if (err < 0)
1673                goto error;
1674        err = ad1983_add_spdif_mux_ctl(codec);
1675        if (err < 0)
1676                goto error;
1677        return 0;
1678
1679 error:
1680        snd_hda_gen_free(codec);
1681        return err;
1682}
1683
1684#ifdef ENABLE_AD_STATIC_QUIRKS
1685static int patch_ad1983(struct hda_codec *codec)
1686{
1687        struct ad198x_spec *spec;
1688        int board_config;
1689        int err;
1690
1691        board_config = snd_hda_check_board_config(codec, AD1983_MODELS,
1692                                                  ad1983_models, NULL);
1693        if (board_config < 0) {
1694                printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
1695                       codec->chip_name);
1696                board_config = AD1983_AUTO;
1697        }
1698
1699        if (board_config == AD1983_AUTO)
1700                return ad1983_parse_auto_config(codec);
1701
1702        err = alloc_ad_spec(codec);
1703        if (err < 0)
1704                return err;
1705        spec = codec->spec;
1706
1707        err = snd_hda_attach_beep_device(codec, 0x10);
1708        if (err < 0) {
1709                ad198x_free(codec);
1710                return err;
1711        }
1712        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1713
1714        spec->multiout.max_channels = 2;
1715        spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
1716        spec->multiout.dac_nids = ad1983_dac_nids;
1717        spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
1718        spec->num_adc_nids = 1;
1719        spec->adc_nids = ad1983_adc_nids;
1720        spec->capsrc_nids = ad1983_capsrc_nids;
1721        spec->input_mux = &ad1983_capture_source;
1722        spec->num_mixers = 1;
1723        spec->mixers[0] = ad1983_mixers;
1724        spec->num_init_verbs = 1;
1725        spec->init_verbs[0] = ad1983_init_verbs;
1726        spec->spdif_route = 0;
1727#ifdef CONFIG_PM
1728        spec->loopback.amplist = ad1983_loopbacks;
1729#endif
1730        spec->vmaster_nid = 0x05;
1731
1732        codec->patch_ops = ad198x_patch_ops;
1733
1734        codec->no_trigger_sense = 1;
1735        codec->no_sticky_stream = 1;
1736
1737        return 0;
1738}
1739#else /* ENABLE_AD_STATIC_QUIRKS */
1740#define patch_ad1983    ad1983_parse_auto_config
1741#endif /* ENABLE_AD_STATIC_QUIRKS */
1742
1743
1744/*
1745 * AD1981 HD specific
1746 */
1747
1748#ifdef ENABLE_AD_STATIC_QUIRKS
1749#define AD1981_SPDIF_OUT        0x02
1750#define AD1981_DAC              0x03
1751#define AD1981_ADC              0x04
1752
1753static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
1754static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
1755static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
1756
1757/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
1758static const struct hda_input_mux ad1981_capture_source = {
1759        .num_items = 7,
1760        .items = {
1761                { "Front Mic", 0x0 },
1762                { "Line", 0x1 },
1763                { "Mix", 0x2 },
1764                { "Mix Mono", 0x3 },
1765                { "CD", 0x4 },
1766                { "Mic", 0x6 },
1767                { "Aux", 0x7 },
1768        },
1769};
1770
1771static const struct snd_kcontrol_new ad1981_mixers[] = {
1772        HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
1773        HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
1774        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1775        HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
1776        HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
1777        HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
1778        HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1779        HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1780        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1781        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1782        HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1783        HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1784        HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1785        HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1786        HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1787        HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1788        HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1789        HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1790        HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
1791        HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
1792        HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
1793        HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
1794        {
1795                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1796                .name = "Capture Source",
1797                .info = ad198x_mux_enum_info,
1798                .get = ad198x_mux_enum_get,
1799                .put = ad198x_mux_enum_put,
1800        },
1801        /* identical with AD1983 */
1802        {
1803                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1804                .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
1805                .info = ad1983_spdif_route_info,
1806                .get = ad1983_spdif_route_get,
1807                .put = ad1983_spdif_route_put,
1808        },
1809        { } /* end */
1810};
1811
1812static const struct hda_verb ad1981_init_verbs[] = {
1813        /* Front, HP, Mono; mute as default */
1814        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1815        {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1816        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1817        /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
1818        {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1819        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1820        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1821        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1822        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1823        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1824        {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1825        /* Front, HP selectors; from Mix */
1826        {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
1827        {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
1828        /* Mono selector; from Mix */
1829        {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
1830        /* Mic Mixer; select Front Mic */
1831        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1832        {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1833        /* Mic boost: 0dB */
1834        {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1835        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1836        /* Record selector: Front mic */
1837        {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
1838        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1839        /* SPDIF route: PCM */
1840        {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
1841        /* Front Pin */
1842        {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1843        /* HP Pin */
1844        {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
1845        /* Mono Pin */
1846        {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
1847        /* Front & Rear Mic Pins */
1848        {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1849        {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
1850        /* Line Pin */
1851        {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
1852        /* Digital Beep */
1853        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
1854        /* Line-Out as Input: disabled */
1855        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1856        { } /* end */
1857};
1858
1859#ifdef CONFIG_PM
1860static const struct hda_amp_list ad1981_loopbacks[] = {
1861        { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
1862        { 0x13, HDA_OUTPUT, 0 }, /* Line */
1863        { 0x1b, HDA_OUTPUT, 0 }, /* Aux */
1864        { 0x1c, HDA_OUTPUT, 0 }, /* Mic */
1865        { 0x1d, HDA_OUTPUT, 0 }, /* CD */
1866        { } /* end */
1867};
1868#endif
1869
1870/*
1871 * Patch for HP nx6320
1872 *
1873 * nx6320 uses EAPD in the reverse way - EAPD-on means the internal
1874 * speaker output enabled _and_ mute-LED off.
1875 */
1876
1877#define AD1981_HP_EVENT         0x37
1878#define AD1981_MIC_EVENT        0x38
1879
1880static const struct hda_verb ad1981_hp_init_verbs[] = {
1881        {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
1882        /* pin sensing on HP and Mic jacks */
1883        {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
1884        {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
1885        {}
1886};
1887
1888/* turn on/off EAPD (+ mute HP) as a master switch */
1889static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1890                                   struct snd_ctl_elem_value *ucontrol)
1891{
1892        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1893        struct ad198x_spec *spec = codec->spec;
1894
1895        if (! ad198x_eapd_put(kcontrol, ucontrol))
1896                return 0;
1897        /* change speaker pin appropriately */
1898        snd_hda_set_pin_ctl(codec, 0x05, spec->cur_eapd ? PIN_OUT : 0);
1899        /* toggle HP mute appropriately */
1900        snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
1901                                 HDA_AMP_MUTE,
1902                                 spec->cur_eapd ? 0 : HDA_AMP_MUTE);
1903        return 1;
1904}
1905
1906/* bind volumes of both NID 0x05 and 0x06 */
1907static const struct hda_bind_ctls ad1981_hp_bind_master_vol = {
1908        .ops = &snd_hda_bind_vol,
1909        .values = {
1910                HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
1911                HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT),
1912                0
1913        },
1914};
1915
1916/* mute internal speaker if HP is plugged */
1917static void ad1981_hp_automute(struct hda_codec *codec)
1918{
1919        unsigned int present;
1920
1921        present = snd_hda_jack_detect(codec, 0x06);
1922        snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
1923                                 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
1924}
1925
1926/* toggle input of built-in and mic jack appropriately */
1927static void ad1981_hp_automic(struct hda_codec *codec)
1928{
1929        static const struct hda_verb mic_jack_on[] = {
1930                {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1931                {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1932                {}
1933        };
1934        static const struct hda_verb mic_jack_off[] = {
1935                {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1936                {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1937                {}
1938        };
1939        unsigned int present;
1940
1941        present = snd_hda_jack_detect(codec, 0x08);
1942        if (present)
1943                snd_hda_sequence_write(codec, mic_jack_on);
1944        else
1945                snd_hda_sequence_write(codec, mic_jack_off);
1946}
1947
1948/* unsolicited event for HP jack sensing */
1949static void ad1981_hp_unsol_event(struct hda_codec *codec,
1950                                  unsigned int res)
1951{
1952        res >>= 26;
1953        switch (res) {
1954        case AD1981_HP_EVENT:
1955                ad1981_hp_automute(codec);
1956                break;
1957        case AD1981_MIC_EVENT:
1958                ad1981_hp_automic(codec);
1959                break;
1960        }
1961}
1962
1963static const struct hda_input_mux ad1981_hp_capture_source = {
1964        .num_items = 3,
1965        .items = {
1966                { "Mic", 0x0 },
1967                { "Dock Mic", 0x1 },
1968                { "Mix", 0x2 },
1969        },
1970};
1971
1972static const struct snd_kcontrol_new ad1981_hp_mixers[] = {
1973        HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
1974        {
1975                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1976                .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
1977                .name = "Master Playback Switch",
1978                .info = ad198x_eapd_info,
1979                .get = ad198x_eapd_get,
1980                .put = ad1981_hp_master_sw_put,
1981                .private_value = 0x05,
1982        },
1983        HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
1984        HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
1985#if 0
1986        /* FIXME: analog mic/line loopback doesn't work with my tests...
1987         *        (although recording is OK)
1988         */
1989        HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
1990        HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
1991        HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1992        HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1993        HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
1994        HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
1995        /* FIXME: does this laptop have analog CD connection? */
1996        HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1997        HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1998#endif
1999        HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
2000        HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT),
2001        HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
2002        HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
2003        {
2004                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2005                .name = "Capture Source",
2006                .info = ad198x_mux_enum_info,
2007                .get = ad198x_mux_enum_get,
2008                .put = ad198x_mux_enum_put,
2009        },
2010        { } /* end */
2011};
2012
2013/* initialize jack-sensing, too */
2014static int ad1981_hp_init(struct hda_codec *codec)
2015{
2016        ad198x_init(codec);
2017        ad1981_hp_automute(codec);
2018        ad1981_hp_automic(codec);
2019        return 0;
2020}
2021
2022/* configuration for Toshiba Laptops */
2023static const struct hda_verb ad1981_toshiba_init_verbs[] = {
2024        {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
2025        /* pin sensing on HP and Mic jacks */
2026        {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
2027        {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT},
2028        {}
2029};
2030
2031static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
2032        HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
2033        HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
2034        { }
2035};
2036
2037/* configuration for Lenovo Thinkpad T60 */
2038static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
2039        HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2040        HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
2041        HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
2042        HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
2043        HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
2044        HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
2045        HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2046        HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
2047        HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT),
2048        HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
2049        HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
2050        {
2051                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2052                .name = "Capture Source",
2053                .info = ad198x_mux_enum_info,
2054                .get = ad198x_mux_enum_get,
2055                .put = ad198x_mux_enum_put,
2056        },
2057        /* identical with AD1983 */
2058        {
2059                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2060                .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
2061                .info = ad1983_spdif_route_info,
2062                .get = ad1983_spdif_route_get,
2063                .put = ad1983_spdif_route_put,
2064        },
2065        { } /* end */
2066};
2067
2068static const struct hda_input_mux ad1981_thinkpad_capture_source = {
2069        .num_items = 3,
2070        .items = {
2071                { "Mic", 0x0 },
2072                { "Mix", 0x2 },
2073                { "CD", 0x4 },
2074        },
2075};
2076
2077/* models */
2078enum {
2079        AD1981_AUTO,
2080        AD1981_BASIC,
2081        AD1981_HP,
2082        AD1981_THINKPAD,
2083        AD1981_TOSHIBA,
2084        AD1981_MODELS
2085};
2086
2087static const char * const ad1981_models[AD1981_MODELS] = {
2088        [AD1981_AUTO]           = "auto",
2089        [AD1981_HP]             = "hp",
2090        [AD1981_THINKPAD]       = "thinkpad",
2091        [AD1981_BASIC]          = "basic",
2092        [AD1981_TOSHIBA]        = "toshiba"
2093};
2094
2095static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
2096        SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
2097        SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
2098        /* All HP models */
2099        SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP),
2100        SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
2101        /* Lenovo Thinkpad T60/X60/Z6xx */
2102        SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD),
2103        /* HP nx6320 (reversed SSID, H/W bug) */
2104        SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
2105        {}
2106};
2107#endif /* ENABLE_AD_STATIC_QUIRKS */
2108
2109
2110/* follow EAPD via vmaster hook */
2111static void ad_vmaster_eapd_hook(void *private_data, int enabled)
2112{
2113        struct hda_codec *codec = private_data;
2114        struct ad198x_spec *spec = codec->spec;
2115        snd_hda_codec_update_cache(codec, spec->eapd_nid, 0,
2116                                   AC_VERB_SET_EAPD_BTLENABLE,
2117                                   enabled ? 0x02 : 0x00);
2118}
2119
2120static void ad1981_fixup_hp_eapd(struct hda_codec *codec,
2121                                 const struct hda_fixup *fix, int action)
2122{
2123        struct ad198x_spec *spec = codec->spec;
2124
2125        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2126                spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
2127                spec->eapd_nid = 0x05;
2128        }
2129}
2130
2131/* set the upper-limit for mixer amp to 0dB for avoiding the possible
2132 * damage by overloading
2133 */
2134static void ad1981_fixup_amp_override(struct hda_codec *codec,
2135                                      const struct hda_fixup *fix, int action)
2136{
2137        if (action == HDA_FIXUP_ACT_PRE_PROBE)
2138                snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2139                                          (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2140                                          (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2141                                          (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2142                                          (1 << AC_AMPCAP_MUTE_SHIFT));
2143}
2144
2145enum {
2146        AD1981_FIXUP_AMP_OVERRIDE,
2147        AD1981_FIXUP_HP_EAPD,
2148};
2149
2150static const struct hda_fixup ad1981_fixups[] = {
2151        [AD1981_FIXUP_AMP_OVERRIDE] = {
2152                .type = HDA_FIXUP_FUNC,
2153                .v.func = ad1981_fixup_amp_override,
2154        },
2155        [AD1981_FIXUP_HP_EAPD] = {
2156                .type = HDA_FIXUP_FUNC,
2157                .v.func = ad1981_fixup_hp_eapd,
2158                .chained = true,
2159                .chain_id = AD1981_FIXUP_AMP_OVERRIDE,
2160        },
2161};
2162
2163static const struct snd_pci_quirk ad1981_fixup_tbl[] = {
2164        SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
2165        SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD),
2166        SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
2167        /* HP nx6320 (reversed SSID, H/W bug) */
2168        SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_FIXUP_HP_EAPD),
2169        {}
2170};
2171
2172static int ad1981_parse_auto_config(struct hda_codec *codec)
2173{
2174        struct ad198x_spec *spec;
2175        int err;
2176
2177        err = alloc_ad_spec(codec);
2178        if (err < 0)
2179                return -ENOMEM;
2180        spec = codec->spec;
2181
2182        spec->gen.mixer_nid = 0x0e;
2183        spec->gen.beep_nid = 0x10;
2184        set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
2185
2186        snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
2187        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
2188
2189        err = ad198x_parse_auto_config(codec);
2190        if (err < 0)
2191                goto error;
2192        err = ad1983_add_spdif_mux_ctl(codec);
2193        if (err < 0)
2194                goto error;
2195
2196        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
2197
2198        return 0;
2199
2200 error:
2201        snd_hda_gen_free(codec);
2202        return err;
2203}
2204
2205#ifdef ENABLE_AD_STATIC_QUIRKS
2206static int patch_ad1981(struct hda_codec *codec)
2207{
2208        struct ad198x_spec *spec;
2209        int err, board_config;
2210
2211        board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
2212                                                  ad1981_models,
2213                                                  ad1981_cfg_tbl);
2214        if (board_config < 0) {
2215                printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
2216                       codec->chip_name);
2217                board_config = AD1981_AUTO;
2218        }
2219
2220        if (board_config == AD1981_AUTO)
2221                return ad1981_parse_auto_config(codec);
2222
2223        err = alloc_ad_spec(codec);
2224        if (err < 0)
2225                return -ENOMEM;
2226        spec = codec->spec;
2227
2228        err = snd_hda_attach_beep_device(codec, 0x10);
2229        if (err < 0) {
2230                ad198x_free(codec);
2231                return err;
2232        }
2233        set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
2234
2235        spec->multiout.max_channels = 2;
2236        spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
2237        spec->multiout.dac_nids = ad1981_dac_nids;
2238        spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
2239        spec->num_adc_nids = 1;
2240        spec->adc_nids = ad1981_adc_nids;
2241        spec->capsrc_nids = ad1981_capsrc_nids;
2242        spec->input_mux = &ad1981_capture_source;
2243        spec->num_mixers = 1;
2244        spec->mixers[0] = ad1981_mixers;
2245        spec->num_init_verbs = 1;
2246        spec->init_verbs[0] = ad1981_init_verbs;
2247        spec->spdif_route = 0;
2248#ifdef CONFIG_PM
2249        spec->loopback.amplist = ad1981_loopbacks;
2250#endif
2251        spec->vmaster_nid = 0x05;
2252
2253        codec->patch_ops = ad198x_patch_ops;
2254
2255        /* override some parameters */
2256        switch (board_config) {
2257        case AD1981_HP:
2258                spec->mixers[0] = ad1981_hp_mixers;
2259                spec->num_init_verbs = 2;
2260                spec->init_verbs[1] = ad1981_hp_init_verbs;
2261                if (!is_jack_available(codec, 0x0a))
2262                        spec->multiout.dig_out_nid = 0;
2263                spec->input_mux = &ad1981_hp_capture_source;
2264
2265                codec->patch_ops.init = ad1981_hp_init;
2266                codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
2267                /* set the upper-limit for mixer amp to 0dB for avoiding the
2268                 * possible damage by overloading
2269                 */
2270                snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2271                                          (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2272                                          (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2273                                          (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2274                                          (1 << AC_AMPCAP_MUTE_SHIFT));
2275                break;
2276        case AD1981_THINKPAD:
2277                spec->mixers[0] = ad1981_thinkpad_mixers;
2278                spec->input_mux = &ad1981_thinkpad_capture_source;
2279                /* set the upper-limit for mixer amp to 0dB for avoiding the
2280                 * possible damage by overloading
2281                 */
2282                snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2283                                          (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2284                                          (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2285                                          (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2286                                          (1 << AC_AMPCAP_MUTE_SHIFT));
2287                break;
2288        case AD1981_TOSHIBA:
2289                spec->mixers[0] = ad1981_hp_mixers;
2290                spec->mixers[1] = ad1981_toshiba_mixers;
2291                spec->num_init_verbs = 2;
2292                spec->init_verbs[1] = ad1981_toshiba_init_verbs;
2293                spec->multiout.dig_out_nid = 0;
2294                spec->input_mux = &ad1981_hp_capture_source;
2295                codec->patch_ops.init = ad1981_hp_init;
2296                codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
2297                break;
2298        }
2299
2300        codec->no_trigger_sense = 1;
2301        codec->no_sticky_stream = 1;
2302
2303        return 0;
2304}
2305#else /* ENABLE_AD_STATIC_QUIRKS */
2306#define patch_ad1981    ad1981_parse_auto_config
2307#endif /* ENABLE_AD_STATIC_QUIRKS */
2308
2309
2310/*
2311 * AD1988
2312 *
2313 * Output pins and routes
2314 *
2315 *        Pin               Mix     Sel     DAC (*)
2316 * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
2317 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
2318 * port-C 0x15 (mute)    <- 0x2c <- 0x31 <- 05/0a
2319 * port-D 0x12 (mute/hp) <- 0x29         <- 04
2320 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
2321 * port-F 0x16 (mute)    <- 0x2a         <- 06
2322 * port-G 0x24 (mute)    <- 0x27         <- 05
2323 * port-H 0x25 (mute)    <- 0x28         <- 0a
2324 * mono   0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
2325 *
2326 * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
2327 * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
2328 *
2329 * Input pins and routes
2330 *
2331 *        pin     boost   mix input # / adc input #
2332 * port-A 0x11 -> 0x38 -> mix 2, ADC 0
2333 * port-B 0x14 -> 0x39 -> mix 0, ADC 1
2334 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
2335 * port-D 0x12 -> 0x3d -> mix 3, ADC 8
2336 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
2337 * port-F 0x16 -> 0x3b -> mix 5, ADC 3
2338 * port-G 0x24 -> N/A  -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
2339 * port-H 0x25 -> N/A  -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
2340 *
2341 *
2342 * DAC assignment
2343 *   6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
2344 *   3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
2345 *
2346 * Inputs of Analog Mix (0x20)
2347 *   0:Port-B (front mic)
2348 *   1:Port-C/G/H (line-in)
2349 *   2:Port-A
2350 *   3:Port-D (line-in/2)
2351 *   4:Port-E/G/H (mic-in)
2352 *   5:Port-F (mic2-in)
2353 *   6:CD
2354 *   7:Beep
2355 *
2356 * ADC selection
2357 *   0:Port-A
2358 *   1:Port-B (front mic-in)
2359 *   2:Port-C (line-in)
2360 *   3:Port-F (mic2-in)
2361 *   4:Port-E (mic-in)
2362 *   5:CD
2363 *   6:Port-G
2364 *   7:Port-H
2365 *   8:Port-D (line-in/2)
2366 *   9:Mix
2367 *
2368 * Proposed pin assignments by the datasheet
2369 *
2370 * 6-stack
2371 * Port-A front headphone
2372 *      B front mic-in
2373 *      C rear line-in
2374 *      D rear front-out
2375 *      E rear mic-in
2376 *      F rear surround
2377 *      G rear CLFE
2378 *      H rear side
2379 *
2380 * 3-stack
2381 * Port-A front headphone
2382 *      B front mic
2383 *      C rear line-in/surround
2384 *      D rear front-out
2385 *      E rear mic-in/CLFE
2386 *
2387 * laptop
2388 * Port-A headphone
2389 *      B mic-in
2390 *      C docking station
2391 *      D internal speaker (with EAPD)
2392 *      E/F quad mic array
2393 */
2394
2395
2396#ifdef ENABLE_AD_STATIC_QUIRKS
2397/* models */
2398enum {
2399        AD1988_AUTO,
2400        AD1988_6STACK,
2401        AD1988_6STACK_DIG,
2402        AD1988_3STACK,
2403        AD1988_3STACK_DIG,
2404        AD1988_LAPTOP,
2405        AD1988_LAPTOP_DIG,
2406        AD1988_MODEL_LAST,
2407};
2408
2409/* reivision id to check workarounds */
2410#define AD1988A_REV2            0x100200
2411
2412#define is_rev2(codec) \
2413        ((codec)->vendor_id == 0x11d41988 && \
2414         (codec)->revision_id == AD1988A_REV2)
2415
2416/*
2417 * mixers
2418 */
2419
2420static const hda_nid_t ad1988_6stack_dac_nids[4] = {
2421        0x04, 0x06, 0x05, 0x0a
2422};
2423
2424static const hda_nid_t ad1988_3stack_dac_nids[3] = {
2425        0x04, 0x05, 0x0a
2426};
2427
2428/* for AD1988A revision-2, DAC2-4 are swapped */
2429static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
2430        0x04, 0x05, 0x0a, 0x06
2431};
2432
2433static const hda_nid_t ad1988_alt_dac_nid[1] = {
2434        0x03
2435};
2436
2437static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
2438        0x04, 0x0a, 0x06
2439};
2440
2441static const hda_nid_t ad1988_adc_nids[3] = {
2442        0x08, 0x09, 0x0f
2443};
2444
2445static const hda_nid_t ad1988_capsrc_nids[3] = {
2446        0x0c, 0x0d, 0x0e
2447};
2448
2449#define AD1988_SPDIF_OUT                0x02
2450#define AD1988_SPDIF_OUT_HDMI   0x0b
2451#define AD1988_SPDIF_IN         0x07
2452
2453static const hda_nid_t ad1989b_slave_dig_outs[] = {
2454        AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
2455};
2456
2457static const struct hda_input_mux ad1988_6stack_capture_source = {
2458        .num_items = 5,
2459        .items = {
2460                { "Front Mic", 0x1 },   /* port-B */
2461                { "Line", 0x2 },        /* port-C */
2462                { "Mic", 0x4 },         /* port-E */
2463                { "CD", 0x5 },
2464                { "Mix", 0x9 },
2465        },
2466};
2467
2468static const struct hda_input_mux ad1988_laptop_capture_source = {
2469        .num_items = 3,
2470        .items = {
2471                { "Mic/Line", 0x1 },    /* port-B */
2472                { "CD", 0x5 },
2473                { "Mix", 0x9 },
2474        },
2475};
2476
2477/*
2478 */
2479static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
2480                               struct snd_ctl_elem_info *uinfo)
2481{
2482        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2483        struct ad198x_spec *spec = codec->spec;
2484        return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
2485                                    spec->num_channel_mode);
2486}
2487
2488static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
2489                              struct snd_ctl_elem_value *ucontrol)
2490{
2491        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2492        struct ad198x_spec *spec = codec->spec;
2493        return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
2494                                   spec->num_channel_mode, spec->multiout.max_channels);
2495}
2496
2497static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
2498                              struct snd_ctl_elem_value *ucontrol)
2499{
2500        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2501        struct ad198x_spec *spec = codec->spec;
2502        int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
2503                                      spec->num_channel_mode,
2504                                      &spec->multiout.max_channels);
2505        if (err >= 0 && spec->need_dac_fix)
2506                spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2507        return err;
2508}
2509
2510/* 6-stack mode */
2511static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
2512        HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2513        HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2514        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2515        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2516        HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2517        { } /* end */
2518};
2519
2520static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
2521        HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2522        HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
2523        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2524        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
2525        HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
2526        { } /* end */
2527};
2528
2529static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
2530        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2531        HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2532        HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
2533        HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
2534        HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
2535        HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
2536        HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2537        HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2538
2539        HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2540        HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2541        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2542        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2543        HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2544        HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2545        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2546        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2547
2548        HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2549        HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2550
2551        HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2552        HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2553        { } /* end */
2554};
2555
2556/* 3-stack mode */
2557static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
2558        HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2559        HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2560        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
2561        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
2562        { } /* end */
2563};
2564
2565static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
2566        HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2567        HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
2568        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
2569        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
2570        { } /* end */
2571};
2572
2573static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
2574        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2575        HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
2576        HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
2577        HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
2578        HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
2579        HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
2580        HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2581
2582        HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2583        HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2584        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2585        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2586        HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2587        HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2588        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
2589        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
2590
2591        HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2592        HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2593
2594        HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2595        HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
2596        {
2597                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2598                .name = "Channel Mode",
2599                .info = ad198x_ch_mode_info,
2600                .get = ad198x_ch_mode_get,
2601                .put = ad198x_ch_mode_put,
2602        },
2603
2604        { } /* end */
2605};
2606
2607/* laptop mode */
2608static const struct snd_kcontrol_new ad1988_laptop_mixers[] = {
2609        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
2610        HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
2611        HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
2612        HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
2613
2614        HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
2615        HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
2616        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
2617        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
2618        HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
2619        HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
2620
2621        HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
2622        HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
2623
2624        HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
2625
2626        {
2627                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2628                .name = "External Amplifier",
2629                .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
2630                .info = ad198x_eapd_info,
2631                .get = ad198x_eapd_get,
2632                .put = ad198x_eapd_put,
2633                .private_value = 0x12, /* port-D */
2634        },
2635
2636        { } /* end */
2637};
2638
2639/* capture */
2640static const struct snd_kcontrol_new ad1988_capture_mixers[] = {
2641        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
2642        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
2643        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
2644        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
2645        HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
2646        HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
2647        {
2648                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2649                /* The multiple "Capture Source" controls confuse alsamixer
2650                 * So call somewhat different..
2651                 */
2652                /* .name = "Capture Source", */
2653                .name = "Input Source",
2654                .count = 3,
2655                .info = ad198x_mux_enum_info,
2656                .get = ad198x_mux_enum_get,
2657                .put = ad198x_mux_enum_put,
2658        },
2659        { } /* end */
2660};
2661
2662static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
2663                                             struct snd_ctl_elem_info *uinfo)
2664{
2665        static const char * const texts[] = {
2666                "PCM", "ADC1", "ADC2", "ADC3"
2667        };
2668        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2669        uinfo->count = 1;
2670        uinfo->value.enumerated.items = 4;
2671        if (uinfo->value.enumerated.item >= 4)
2672                uinfo->value.enumerated.item = 3;
2673        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2674        return 0;
2675}
2676
2677static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
2678                                            struct snd_ctl_elem_value *ucontrol)
2679{
2680        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2681        unsigned int sel;
2682
2683        sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE,
2684                                 AC_AMP_GET_INPUT);
2685        if (!(sel & 0x80))
2686                ucontrol->value.enumerated.item[0] = 0;
2687        else {
2688                sel = snd_hda_codec_read(codec, 0x0b, 0,
2689                                         AC_VERB_GET_CONNECT_SEL, 0);
2690                if (sel < 3)
2691                        sel++;
2692                else
2693                        sel = 0;
2694                ucontrol->value.enumerated.item[0] = sel;
2695        }
2696        return 0;
2697}
2698
2699static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
2700                                            struct snd_ctl_elem_value *ucontrol)
2701{
2702        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2703        unsigned int val, sel;
2704        int change;
2705
2706        val = ucontrol->value.enumerated.item[0];
2707        if (val > 3)
2708                return -EINVAL;
2709        if (!val) {
2710                sel = snd_hda_codec_read(codec, 0x1d, 0,
2711                                         AC_VERB_GET_AMP_GAIN_MUTE,
2712                                         AC_AMP_GET_INPUT);
2713                change = sel & 0x80;
2714                if (change) {
2715                        snd_hda_codec_write_cache(codec, 0x1d, 0,
2716                                                  AC_VERB_SET_AMP_GAIN_MUTE,
2717                                                  AMP_IN_UNMUTE(0));
2718                        snd_hda_codec_write_cache(codec, 0x1d, 0,
2719                                                  AC_VERB_SET_AMP_GAIN_MUTE,
2720                                                  AMP_IN_MUTE(1));
2721                }
2722        } else {
2723                sel = snd_hda_codec_read(codec, 0x1d, 0,
2724                                         AC_VERB_GET_AMP_GAIN_MUTE,
2725                                         AC_AMP_GET_INPUT | 0x01);
2726                change = sel & 0x80;
2727                if (change) {
2728                        snd_hda_codec_write_cache(codec, 0x1d, 0,
2729                                                  AC_VERB_SET_AMP_GAIN_MUTE,
2730                                                  AMP_IN_MUTE(0));
2731                        snd_hda_codec_write_cache(codec, 0x1d, 0,
2732                                                  AC_VERB_SET_AMP_GAIN_MUTE,
2733                                                  AMP_IN_UNMUTE(1));
2734                }
2735                sel = snd_hda_codec_read(codec, 0x0b, 0,
2736                                         AC_VERB_GET_CONNECT_SEL, 0) + 1;
2737                change |= sel != val;
2738                if (change)
2739                        snd_hda_codec_write_cache(codec, 0x0b, 0,
2740                                                  AC_VERB_SET_CONNECT_SEL,
2741                                                  val - 1);
2742        }
2743        return change;
2744}
2745
2746static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
2747        HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2748        {
2749                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2750                .name = "IEC958 Playback Source",
2751                .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
2752                .info = ad1988_spdif_playback_source_info,
2753                .get = ad1988_spdif_playback_source_get,
2754                .put = ad1988_spdif_playback_source_put,
2755        },
2756        { } /* end */
2757};
2758
2759static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
2760        HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
2761        { } /* end */
2762};
2763
2764static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
2765        HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
2766        HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
2767        { } /* end */
2768};
2769
2770/*
2771 * initialization verbs
2772 */
2773
2774/*
2775 * for 6-stack (+dig)
2776 */
2777static const struct hda_verb ad1988_6stack_init_verbs[] = {
2778        /* Front, Surround, CLFE, side DAC; unmute as default */
2779        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2780        {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2781        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2782        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2783        /* Port-A front headphon path */
2784        {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2785        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2786        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2787        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2788        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2789        /* Port-D line-out path */
2790        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2791        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2792        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2793        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2794        /* Port-F surround path */
2795        {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2796        {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2797        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2798        {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2799        /* Port-G CLFE path */
2800        {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2801        {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2802        {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2803        {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2804        /* Port-H side path */
2805        {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2806        {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2807        {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2808        {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2809        /* Mono out path */
2810        {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2811        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2812        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2813        {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2814        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2815        /* Port-B front mic-in path */
2816        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2817        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2818        {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2819        /* Port-C line-in path */
2820        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2821        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2822        {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2823        {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2824        /* Port-E mic-in path */
2825        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2826        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2827        {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2828        {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2829        /* Analog CD Input */
2830        {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2831        /* Analog Mix output amp */
2832        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2833
2834        { }
2835};
2836
2837static const struct hda_verb ad1988_6stack_fp_init_verbs[] = {
2838        /* Headphone; unmute as default */
2839        {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2840        /* Port-A front headphon path */
2841        {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2842        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2843        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2844        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2845        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2846
2847        { }
2848};
2849
2850static const struct hda_verb ad1988_capture_init_verbs[] = {
2851        /* mute analog mix */
2852        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2853        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2854        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2855        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2856        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2857        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2858        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2859        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2860        /* select ADCs - front-mic */
2861        {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2862        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2863        {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2864
2865        { }
2866};
2867
2868static const struct hda_verb ad1988_spdif_init_verbs[] = {
2869        /* SPDIF out sel */
2870        {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
2871        {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
2872        {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2873        {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2874        /* SPDIF out pin */
2875        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2876
2877        { }
2878};
2879
2880static const struct hda_verb ad1988_spdif_in_init_verbs[] = {
2881        /* unmute SPDIF input pin */
2882        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2883        { }
2884};
2885
2886/* AD1989 has no ADC -> SPDIF route */
2887static const struct hda_verb ad1989_spdif_init_verbs[] = {
2888        /* SPDIF-1 out pin */
2889        {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2890        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2891        /* SPDIF-2/HDMI out pin */
2892        {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2893        {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
2894        { }
2895};
2896
2897/*
2898 * verbs for 3stack (+dig)
2899 */
2900static const struct hda_verb ad1988_3stack_ch2_init[] = {
2901        /* set port-C to line-in */
2902        { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2903        { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
2904        /* set port-E to mic-in */
2905        { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2906        { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
2907        { } /* end */
2908};
2909
2910static const struct hda_verb ad1988_3stack_ch6_init[] = {
2911        /* set port-C to surround out */
2912        { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2913        { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2914        /* set port-E to CLFE out */
2915        { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
2916        { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2917        { } /* end */
2918};
2919
2920static const struct hda_channel_mode ad1988_3stack_modes[2] = {
2921        { 2, ad1988_3stack_ch2_init },
2922        { 6, ad1988_3stack_ch6_init },
2923};
2924
2925static const struct hda_verb ad1988_3stack_init_verbs[] = {
2926        /* Front, Surround, CLFE, side DAC; unmute as default */
2927        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2928        {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2929        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2930        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2931        /* Port-A front headphon path */
2932        {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
2933        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2934        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2935        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2936        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2937        /* Port-D line-out path */
2938        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2939        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2940        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2941        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2942        /* Mono out path */
2943        {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
2944        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2945        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2946        {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2947        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
2948        /* Port-B front mic-in path */
2949        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2950        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2951        {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2952        /* Port-C line-in/surround path - 6ch mode as default */
2953        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2954        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2955        {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2956        {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
2957        {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
2958        /* Port-E mic-in/CLFE path - 6ch mode as default */
2959        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2960        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2961        {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2962        {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
2963        {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
2964        /* mute analog mix */
2965        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2966        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2967        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2968        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2969        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2970        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
2971        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
2972        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
2973        /* select ADCs - front-mic */
2974        {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
2975        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
2976        {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
2977        /* Analog Mix output amp */
2978        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
2979        { }
2980};
2981
2982/*
2983 * verbs for laptop mode (+dig)
2984 */
2985static const struct hda_verb ad1988_laptop_hp_on[] = {
2986        /* unmute port-A and mute port-D */
2987        { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2988        { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2989        { } /* end */
2990};
2991static const struct hda_verb ad1988_laptop_hp_off[] = {
2992        /* mute port-A and unmute port-D */
2993        { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2994        { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
2995        { } /* end */
2996};
2997
2998#define AD1988_HP_EVENT 0x01
2999
3000static const struct hda_verb ad1988_laptop_init_verbs[] = {
3001        /* Front, Surround, CLFE, side DAC; unmute as default */
3002        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3003        {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3004        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3005        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3006        /* Port-A front headphon path */
3007        {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
3008        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3009        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3010        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3011        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3012        /* unsolicited event for pin-sense */
3013        {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
3014        /* Port-D line-out path + EAPD */
3015        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3016        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3017        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3018        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3019        {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
3020        /* Mono out path */
3021        {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
3022        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3023        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3024        {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3025        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
3026        /* Port-B mic-in path */
3027        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3028        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3029        {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3030        /* Port-C docking station - try to output */
3031        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3032        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3033        {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3034        {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
3035        /* mute analog mix */
3036        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3037        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3038        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3039        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3040        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3041        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
3042        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
3043        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
3044        /* select ADCs - mic */
3045        {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
3046        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
3047        {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3048        /* Analog Mix output amp */
3049        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3050        { }
3051};
3052
3053static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
3054{
3055        if ((res >> 26) != AD1988_HP_EVENT)
3056                return;
3057        if (snd_hda_jack_detect(codec, 0x11))
3058                snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
3059        else
3060                snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
3061} 
3062
3063#ifdef CONFIG_PM
3064static const struct hda_amp_list ad1988_loopbacks[] = {
3065        { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3066        { 0x20, HDA_INPUT, 1 }, /* Line */
3067        { 0x20, HDA_INPUT, 4 }, /* Mic */
3068        { 0x20, HDA_INPUT, 6 }, /* CD */
3069        { } /* end */
3070};
3071#endif
3072#endif /* ENABLE_AD_STATIC_QUIRKS */
3073
3074static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
3075                                      struct snd_ctl_elem_info *uinfo)
3076{
3077        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3078        static const char * const texts[] = {
3079                "PCM", "ADC1", "ADC2", "ADC3",
3080        };
3081        int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
3082        if (num_conns > 4)
3083                num_conns = 4;
3084        return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
3085}
3086
3087static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
3088                                     struct snd_ctl_elem_value *ucontrol)
3089{
3090        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3091        struct ad198x_spec *spec = codec->spec;
3092
3093        ucontrol->value.enumerated.item[0] = spec->cur_smux;
3094        return 0;
3095}
3096
3097static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
3098                                     struct snd_ctl_elem_value *ucontrol)
3099{
3100        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3101        struct ad198x_spec *spec = codec->spec;
3102        unsigned int val = ucontrol->value.enumerated.item[0];
3103        struct nid_path *path;
3104        int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
3105
3106        if (val >= num_conns)
3107                return -EINVAL;
3108        if (spec->cur_smux == val)
3109                return 0;
3110
3111        mutex_lock(&codec->control_mutex);
3112        codec->cached_write = 1;
3113        path = snd_hda_get_path_from_idx(codec,
3114                                         spec->smux_paths[spec->cur_smux]);
3115        if (path)
3116                snd_hda_activate_path(codec, path, false, true);
3117        path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]);
3118        if (path)
3119                snd_hda_activate_path(codec, path, true, true);
3120        spec->cur_smux = val;
3121        codec->cached_write = 0;
3122        mutex_unlock(&codec->control_mutex);
3123        snd_hda_codec_flush_cache(codec); /* flush the updates */
3124        return 1;
3125}
3126
3127static struct snd_kcontrol_new ad1988_auto_smux_mixer = {
3128        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3129        .name = "IEC958 Playback Source",
3130        .info = ad1988_auto_smux_enum_info,
3131        .get = ad1988_auto_smux_enum_get,
3132        .put = ad1988_auto_smux_enum_put,
3133};
3134
3135static int ad1988_auto_init(struct hda_codec *codec)
3136{
3137        struct ad198x_spec *spec = codec->spec;
3138        int i, err;
3139
3140        err = snd_hda_gen_init(codec);
3141        if (err < 0)
3142                return err;
3143        if (!spec->gen.autocfg.dig_outs)
3144                return 0;
3145
3146        for (i = 0; i < 4; i++) {
3147                struct nid_path *path;
3148                path = snd_hda_get_path_from_idx(codec, spec->smux_paths[i]);
3149                if (path)
3150                        snd_hda_activate_path(codec, path, path->active, false);
3151        }
3152
3153        return 0;
3154}
3155
3156static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
3157{
3158        struct ad198x_spec *spec = codec->spec;
3159        int i, num_conns;
3160        /* we create four static faked paths, since AD codecs have odd
3161         * widget connections regarding the SPDIF out source
3162         */
3163        static struct nid_path fake_paths[4] = {
3164                {
3165                        .depth = 3,
3166                        .path = { 0x02, 0x1d, 0x1b },
3167                        .idx = { 0, 0, 0 },
3168                        .multi = { 0, 0, 0 },
3169                },
3170                {
3171                        .depth = 4,
3172                        .path = { 0x08, 0x0b, 0x1d, 0x1b },
3173                        .idx = { 0, 0, 1, 0 },
3174                        .multi = { 0, 1, 0, 0 },
3175                },
3176                {
3177                        .depth = 4,
3178                        .path = { 0x09, 0x0b, 0x1d, 0x1b },
3179                        .idx = { 0, 1, 1, 0 },
3180                        .multi = { 0, 1, 0, 0 },
3181                },
3182                {
3183                        .depth = 4,
3184                        .path = { 0x0f, 0x0b, 0x1d, 0x1b },
3185                        .idx = { 0, 2, 1, 0 },
3186                        .multi = { 0, 1, 0, 0 },
3187                },
3188        };
3189
3190        /* SPDIF source mux appears to be present only on AD1988A */
3191        if (!spec->gen.autocfg.dig_outs ||
3192            get_wcaps_type(get_wcaps(codec, 0x1d)) != AC_WID_AUD_MIX)
3193                return 0;
3194
3195        num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
3196        if (num_conns != 3 && num_conns != 4)
3197                return 0;
3198
3199        for (i = 0; i < num_conns; i++) {
3200                struct nid_path *path = snd_array_new(&spec->gen.paths);
3201                if (!path)
3202                        return -ENOMEM;
3203                *path = fake_paths[i];
3204                if (!i)
3205                        path->active = 1;
3206                spec->smux_paths[i] = snd_hda_get_path_idx(codec, path);
3207        }
3208
3209        if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1988_auto_smux_mixer))
3210                return -ENOMEM;
3211
3212        codec->patch_ops.init = ad1988_auto_init;
3213
3214        return 0;
3215}
3216
3217/*
3218 */
3219
3220static int ad1988_parse_auto_config(struct hda_codec *codec)
3221{
3222        struct ad198x_spec *spec;
3223        int err;
3224
3225        err = alloc_ad_spec(codec);
3226        if (err < 0)
3227                return err;
3228        spec = codec->spec;
3229
3230        spec->gen.mixer_nid = 0x20;
3231        spec->gen.mixer_merge_nid = 0x21;
3232        spec->gen.beep_nid = 0x10;
3233        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3234        err = ad198x_parse_auto_config(codec);
3235        if (err < 0)
3236                goto error;
3237        err = ad1988_add_spdif_mux_ctl(codec);
3238        if (err < 0)
3239                goto error;
3240        return 0;
3241
3242 error:
3243        snd_hda_gen_free(codec);
3244        return err;
3245}
3246
3247/*
3248 */
3249
3250#ifdef ENABLE_AD_STATIC_QUIRKS
3251static const char * const ad1988_models[AD1988_MODEL_LAST] = {
3252        [AD1988_6STACK]         = "6stack",
3253        [AD1988_6STACK_DIG]     = "6stack-dig",
3254        [AD1988_3STACK]         = "3stack",
3255        [AD1988_3STACK_DIG]     = "3stack-dig",
3256        [AD1988_LAPTOP]         = "laptop",
3257        [AD1988_LAPTOP_DIG]     = "laptop-dig",
3258        [AD1988_AUTO]           = "auto",
3259};
3260
3261static const struct snd_pci_quirk ad1988_cfg_tbl[] = {
3262        SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
3263        SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
3264        SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
3265        SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG),
3266        SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
3267        {}
3268};
3269
3270static int patch_ad1988(struct hda_codec *codec)
3271{
3272        struct ad198x_spec *spec;
3273        int err, board_config;
3274
3275        board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
3276                                                  ad1988_models, ad1988_cfg_tbl);
3277        if (board_config < 0) {
3278                printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3279                       codec->chip_name);
3280                board_config = AD1988_AUTO;
3281        }
3282
3283        if (board_config == AD1988_AUTO)
3284                return ad1988_parse_auto_config(codec);
3285
3286        err = alloc_ad_spec(codec);
3287        if (err < 0)
3288                return err;
3289        spec = codec->spec;
3290
3291        if (is_rev2(codec))
3292                snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
3293
3294        err = snd_hda_attach_beep_device(codec, 0x10);
3295        if (err < 0) {
3296                ad198x_free(codec);
3297                return err;
3298        }
3299        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3300
3301        if (!spec->multiout.hp_nid)
3302                spec->multiout.hp_nid = ad1988_alt_dac_nid[0];
3303        switch (board_config) {
3304        case AD1988_6STACK:
3305        case AD1988_6STACK_DIG:
3306                spec->multiout.max_channels = 8;
3307                spec->multiout.num_dacs = 4;
3308                if (is_rev2(codec))
3309                        spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
3310                else
3311                        spec->multiout.dac_nids = ad1988_6stack_dac_nids;
3312                spec->input_mux = &ad1988_6stack_capture_source;
3313                spec->num_mixers = 2;
3314                if (is_rev2(codec))
3315                        spec->mixers[0] = ad1988_6stack_mixers1_rev2;
3316                else
3317                        spec->mixers[0] = ad1988_6stack_mixers1;
3318                spec->mixers[1] = ad1988_6stack_mixers2;
3319                spec->num_init_verbs = 1;
3320                spec->init_verbs[0] = ad1988_6stack_init_verbs;
3321                if (board_config == AD1988_6STACK_DIG) {
3322                        spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3323                        spec->dig_in_nid = AD1988_SPDIF_IN;
3324                }
3325                break;
3326        case AD1988_3STACK:
3327        case AD1988_3STACK_DIG:
3328                spec->multiout.max_channels = 6;
3329                spec->multiout.num_dacs = 3;
3330                if (is_rev2(codec))
3331                        spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
3332                else
3333                        spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3334                spec->input_mux = &ad1988_6stack_capture_source;
3335                spec->channel_mode = ad1988_3stack_modes;
3336                spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
3337                spec->num_mixers = 2;
3338                if (is_rev2(codec))
3339                        spec->mixers[0] = ad1988_3stack_mixers1_rev2;
3340                else
3341                        spec->mixers[0] = ad1988_3stack_mixers1;
3342                spec->mixers[1] = ad1988_3stack_mixers2;
3343                spec->num_init_verbs = 1;
3344                spec->init_verbs[0] = ad1988_3stack_init_verbs;
3345                if (board_config == AD1988_3STACK_DIG)
3346                        spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3347                break;
3348        case AD1988_LAPTOP:
3349        case AD1988_LAPTOP_DIG:
3350                spec->multiout.max_channels = 2;
3351                spec->multiout.num_dacs = 1;
3352                spec->multiout.dac_nids = ad1988_3stack_dac_nids;
3353                spec->input_mux = &ad1988_laptop_capture_source;
3354                spec->num_mixers = 1;
3355                spec->mixers[0] = ad1988_laptop_mixers;
3356                codec->inv_eapd = 1; /* inverted EAPD */
3357                spec->num_init_verbs = 1;
3358                spec->init_verbs[0] = ad1988_laptop_init_verbs;
3359                if (board_config == AD1988_LAPTOP_DIG)
3360                        spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
3361                break;
3362        }
3363
3364        spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
3365        spec->adc_nids = ad1988_adc_nids;
3366        spec->capsrc_nids = ad1988_capsrc_nids;
3367        spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
3368        spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
3369        if (spec->multiout.dig_out_nid) {
3370                if (codec->vendor_id >= 0x11d4989a) {
3371                        spec->mixers[spec->num_mixers++] =
3372                                ad1989_spdif_out_mixers;
3373                        spec->init_verbs[spec->num_init_verbs++] =
3374                                ad1989_spdif_init_verbs;
3375                        codec->slave_dig_outs = ad1989b_slave_dig_outs;
3376                } else {
3377                        spec->mixers[spec->num_mixers++] =
3378                                ad1988_spdif_out_mixers;
3379                        spec->init_verbs[spec->num_init_verbs++] =
3380                                ad1988_spdif_init_verbs;
3381                }
3382        }
3383        if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) {
3384                spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
3385                spec->init_verbs[spec->num_init_verbs++] =
3386                        ad1988_spdif_in_init_verbs;
3387        }
3388
3389        codec->patch_ops = ad198x_patch_ops;
3390        switch (board_config) {
3391        case AD1988_LAPTOP:
3392        case AD1988_LAPTOP_DIG:
3393                codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
3394                break;
3395        }
3396#ifdef CONFIG_PM
3397        spec->loopback.amplist = ad1988_loopbacks;
3398#endif
3399        spec->vmaster_nid = 0x04;
3400
3401        codec->no_trigger_sense = 1;
3402        codec->no_sticky_stream = 1;
3403
3404        return 0;
3405}
3406#else /* ENABLE_AD_STATIC_QUIRKS */
3407#define patch_ad1988    ad1988_parse_auto_config
3408#endif /* ENABLE_AD_STATIC_QUIRKS */
3409
3410
3411/*
3412 * AD1884 / AD1984
3413 *
3414 * port-B - front line/mic-in
3415 * port-E - aux in/out
3416 * port-F - aux in/out
3417 * port-C - rear line/mic-in
3418 * port-D - rear line/hp-out
3419 * port-A - front line/hp-out
3420 *
3421 * AD1984 = AD1884 + two digital mic-ins
3422 *
3423 * FIXME:
3424 * For simplicity, we share the single DAC for both HP and line-outs
3425 * right now.  The inidividual playbacks could be easily implemented,
3426 * but no build-up framework is given, so far.
3427 */
3428
3429#ifdef ENABLE_AD_STATIC_QUIRKS
3430static const hda_nid_t ad1884_dac_nids[1] = {
3431        0x04,
3432};
3433
3434static const hda_nid_t ad1884_adc_nids[2] = {
3435        0x08, 0x09,
3436};
3437
3438static const hda_nid_t ad1884_capsrc_nids[2] = {
3439        0x0c, 0x0d,
3440};
3441
3442#define AD1884_SPDIF_OUT        0x02
3443
3444static const struct hda_input_mux ad1884_capture_source = {
3445        .num_items = 4,
3446        .items = {
3447                { "Front Mic", 0x0 },
3448                { "Mic", 0x1 },
3449                { "CD", 0x2 },
3450                { "Mix", 0x3 },
3451        },
3452};
3453
3454static const struct snd_kcontrol_new ad1884_base_mixers[] = {
3455        HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3456        /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3457        HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3458        HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3459        HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3460        HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3461        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3462        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3463        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3464        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3465        HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
3466        HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
3467        HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3468        HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3469        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3470        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3471        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3472        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3473        {
3474                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3475                /* The multiple "Capture Source" controls confuse alsamixer
3476                 * So call somewhat different..
3477                 */
3478                /* .name = "Capture Source", */
3479                .name = "Input Source",
3480                .count = 2,
3481                .info = ad198x_mux_enum_info,
3482                .get = ad198x_mux_enum_get,
3483                .put = ad198x_mux_enum_put,
3484        },
3485        /* SPDIF controls */
3486        HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3487        {
3488                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3489                .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3490                /* identical with ad1983 */
3491                .info = ad1983_spdif_route_info,
3492                .get = ad1983_spdif_route_get,
3493                .put = ad1983_spdif_route_put,
3494        },
3495        { } /* end */
3496};
3497
3498static const struct snd_kcontrol_new ad1984_dmic_mixers[] = {
3499        HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
3500        HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
3501        HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
3502                             HDA_INPUT),
3503        HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0,
3504                           HDA_INPUT),
3505        { } /* end */
3506};
3507
3508/*
3509 * initialization verbs
3510 */
3511static const struct hda_verb ad1884_init_verbs[] = {
3512        /* DACs; mute as default */
3513        {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3514        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3515        /* Port-A (HP) mixer */
3516        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3517        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3518        /* Port-A pin */
3519        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3520        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3521        /* HP selector - select DAC2 */
3522        {0x22, AC_VERB_SET_CONNECT_SEL, 0x1},
3523        /* Port-D (Line-out) mixer */
3524        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3525        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3526        /* Port-D pin */
3527        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3528        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3529        /* Mono-out mixer */
3530        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3531        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3532        /* Mono-out pin */
3533        {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3534        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3535        /* Mono selector */
3536        {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
3537        /* Port-B (front mic) pin */
3538        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3539        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3540        /* Port-C (rear mic) pin */
3541        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3542        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3543        /* Analog mixer; mute as default */
3544        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3545        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
3546        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
3547        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
3548        /* Analog Mix output amp */
3549        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
3550        /* SPDIF output selector */
3551        {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
3552        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
3553        { } /* end */
3554};
3555
3556#ifdef CONFIG_PM
3557static const struct hda_amp_list ad1884_loopbacks[] = {
3558        { 0x20, HDA_INPUT, 0 }, /* Front Mic */
3559        { 0x20, HDA_INPUT, 1 }, /* Mic */
3560        { 0x20, HDA_INPUT, 2 }, /* CD */
3561        { 0x20, HDA_INPUT, 4 }, /* Docking */
3562        { } /* end */
3563};
3564#endif
3565
3566static const char * const ad1884_slave_vols[] = {
3567        "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD",
3568        "Internal Mic", "Dock Mic", /* "Beep", */ "IEC958",
3569        NULL
3570};
3571
3572enum {
3573        AD1884_AUTO,
3574        AD1884_BASIC,
3575        AD1884_MODELS
3576};
3577
3578static const char * const ad1884_models[AD1884_MODELS] = {
3579        [AD1884_AUTO]           = "auto",
3580        [AD1884_BASIC]          = "basic",
3581};
3582#endif /* ENABLE_AD_STATIC_QUIRKS */
3583
3584
3585/* set the upper-limit for mixer amp to 0dB for avoiding the possible
3586 * damage by overloading
3587 */
3588static void ad1884_fixup_amp_override(struct hda_codec *codec,
3589                                      const struct hda_fixup *fix, int action)
3590{
3591        if (action == HDA_FIXUP_ACT_PRE_PROBE)
3592                snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
3593                                          (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
3594                                          (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
3595                                          (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
3596                                          (1 << AC_AMPCAP_MUTE_SHIFT));
3597}
3598
3599static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
3600                                 const struct hda_fixup *fix, int action)
3601{
3602        struct ad198x_spec *spec = codec->spec;
3603
3604        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3605                if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3606                        spec->eapd_nid = spec->gen.autocfg.line_out_pins[0];
3607                else
3608                        spec->eapd_nid = spec->gen.autocfg.speaker_pins[0];
3609                if (spec->eapd_nid)
3610                        spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
3611        }
3612}
3613
3614enum {
3615        AD1884_FIXUP_AMP_OVERRIDE,
3616        AD1884_FIXUP_HP_EAPD,
3617};
3618
3619static const struct hda_fixup ad1884_fixups[] = {
3620        [AD1884_FIXUP_AMP_OVERRIDE] = {
3621                .type = HDA_FIXUP_FUNC,
3622                .v.func = ad1884_fixup_amp_override,
3623        },
3624        [AD1884_FIXUP_HP_EAPD] = {
3625                .type = HDA_FIXUP_FUNC,
3626                .v.func = ad1884_fixup_hp_eapd,
3627                .chained = true,
3628                .chain_id = AD1884_FIXUP_AMP_OVERRIDE,
3629        },
3630};
3631
3632static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
3633        SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
3634        {}
3635};
3636
3637
3638static int ad1884_parse_auto_config(struct hda_codec *codec)
3639{
3640        struct ad198x_spec *spec;
3641        int err;
3642
3643        err = alloc_ad_spec(codec);
3644        if (err < 0)
3645                return err;
3646        spec = codec->spec;
3647
3648        spec->gen.mixer_nid = 0x20;
3649        spec->gen.beep_nid = 0x10;
3650        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3651
3652        snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
3653        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
3654
3655        err = ad198x_parse_auto_config(codec);
3656        if (err < 0)
3657                goto error;
3658        err = ad1983_add_spdif_mux_ctl(codec);
3659        if (err < 0)
3660                goto error;
3661
3662        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
3663
3664        return 0;
3665
3666 error:
3667        snd_hda_gen_free(codec);
3668        return err;
3669}
3670
3671#ifdef ENABLE_AD_STATIC_QUIRKS
3672static int patch_ad1884_basic(struct hda_codec *codec)
3673{
3674        struct ad198x_spec *spec;
3675        int err;
3676
3677        err = alloc_ad_spec(codec);
3678        if (err < 0)
3679                return err;
3680        spec = codec->spec;
3681
3682        err = snd_hda_attach_beep_device(codec, 0x10);
3683        if (err < 0) {
3684                ad198x_free(codec);
3685                return err;
3686        }
3687        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3688
3689        spec->multiout.max_channels = 2;
3690        spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids);
3691        spec->multiout.dac_nids = ad1884_dac_nids;
3692        spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3693        spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids);
3694        spec->adc_nids = ad1884_adc_nids;
3695        spec->capsrc_nids = ad1884_capsrc_nids;
3696        spec->input_mux = &ad1884_capture_source;
3697        spec->num_mixers = 1;
3698        spec->mixers[0] = ad1884_base_mixers;
3699        spec->num_init_verbs = 1;
3700        spec->init_verbs[0] = ad1884_init_verbs;
3701        spec->spdif_route = 0;
3702#ifdef CONFIG_PM
3703        spec->loopback.amplist = ad1884_loopbacks;
3704#endif
3705        spec->vmaster_nid = 0x04;
3706        /* we need to cover all playback volumes */
3707        spec->slave_vols = ad1884_slave_vols;
3708        /* slaves may contain input volumes, so we can't raise to 0dB blindly */
3709        spec->avoid_init_slave_vol = 1;
3710
3711        codec->patch_ops = ad198x_patch_ops;
3712
3713        codec->no_trigger_sense = 1;
3714        codec->no_sticky_stream = 1;
3715
3716        return 0;
3717}
3718
3719static int patch_ad1884(struct hda_codec *codec)
3720{
3721        int board_config;
3722
3723        board_config = snd_hda_check_board_config(codec, AD1884_MODELS,
3724                                                  ad1884_models, NULL);
3725        if (board_config < 0) {
3726                printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3727                       codec->chip_name);
3728                board_config = AD1884_AUTO;
3729        }
3730
3731        if (board_config == AD1884_AUTO)
3732                return ad1884_parse_auto_config(codec);
3733        else
3734                return patch_ad1884_basic(codec);
3735}
3736#else /* ENABLE_AD_STATIC_QUIRKS */
3737#define patch_ad1884    ad1884_parse_auto_config
3738#endif /* ENABLE_AD_STATIC_QUIRKS */
3739
3740
3741#ifdef ENABLE_AD_STATIC_QUIRKS
3742/*
3743 * Lenovo Thinkpad T61/X61
3744 */
3745static const struct hda_input_mux ad1984_thinkpad_capture_source = {
3746        .num_items = 4,
3747        .items = {
3748                { "Mic", 0x0 },
3749                { "Internal Mic", 0x1 },
3750                { "Mix", 0x3 },
3751                { "Dock Mic", 0x4 },
3752        },
3753};
3754
3755
3756/*
3757 * Dell Precision T3400
3758 */
3759static const struct hda_input_mux ad1984_dell_desktop_capture_source = {
3760        .num_items = 3,
3761        .items = {
3762                { "Front Mic", 0x0 },
3763                { "Line-In", 0x1 },
3764                { "Mix", 0x3 },
3765        },
3766};
3767
3768
3769static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3770        HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3771        /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
3772        HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3773        HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3774        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3775        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3776        HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3777        HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3778        HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3779        HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3780        HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3781        HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3782        HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3783        HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
3784        HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
3785        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3786        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3787        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3788        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3789        {
3790                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3791                /* The multiple "Capture Source" controls confuse alsamixer
3792                 * So call somewhat different..
3793                 */
3794                /* .name = "Capture Source", */
3795                .name = "Input Source",
3796                .count = 2,
3797                .info = ad198x_mux_enum_info,
3798                .get = ad198x_mux_enum_get,
3799                .put = ad198x_mux_enum_put,
3800        },
3801        /* SPDIF controls */
3802        HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
3803        {
3804                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3805                .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
3806                /* identical with ad1983 */
3807                .info = ad1983_spdif_route_info,
3808                .get = ad1983_spdif_route_get,
3809                .put = ad1983_spdif_route_put,
3810        },
3811        { } /* end */
3812};
3813
3814/* additional verbs */
3815static const struct hda_verb ad1984_thinkpad_init_verbs[] = {
3816        /* Port-E (docking station mic) pin */
3817        {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
3818        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3819        /* docking mic boost */
3820        {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3821        /* Analog PC Beeper - allow firmware/ACPI beeps */
3822        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3823        /* Analog mixer - docking mic; mute as default */
3824        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3825        /* enable EAPD bit */
3826        {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
3827        { } /* end */
3828};
3829
3830/*
3831 * Dell Precision T3400
3832 */
3833static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
3834        HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
3835        HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
3836        HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
3837        HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
3838        HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
3839        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
3840        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3841        HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
3842        HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
3843        HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT),
3844        HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
3845        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
3846        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
3847        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
3848        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
3849        {
3850                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3851                /* The multiple "Capture Source" controls confuse alsamixer
3852                 * So call somewhat different..
3853                 */
3854                /* .name = "Capture Source", */
3855                .name = "Input Source",
3856                .count = 2,
3857                .info = ad198x_mux_enum_info,
3858                .get = ad198x_mux_enum_get,
3859                .put = ad198x_mux_enum_put,
3860        },
3861        { } /* end */
3862};
3863
3864/* Digial MIC ADC NID 0x05 + 0x06 */
3865static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
3866                                   struct hda_codec *codec,
3867                                   unsigned int stream_tag,
3868                                   unsigned int format,
3869                                   struct snd_pcm_substream *substream)
3870{
3871        snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
3872                                   stream_tag, 0, format);
3873        return 0;
3874}
3875
3876static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
3877                                   struct hda_codec *codec,
3878                                   struct snd_pcm_substream *substream)
3879{
3880        snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
3881        return 0;
3882}
3883
3884static const struct hda_pcm_stream ad1984_pcm_dmic_capture = {
3885        .substreams = 2,
3886        .channels_min = 2,
3887        .channels_max = 2,
3888        .nid = 0x05,
3889        .ops = {
3890                .prepare = ad1984_pcm_dmic_prepare,
3891                .cleanup = ad1984_pcm_dmic_cleanup
3892        },
3893};
3894
3895static int ad1984_build_pcms(struct hda_codec *codec)
3896{
3897        struct ad198x_spec *spec = codec->spec;
3898        struct hda_pcm *info;
3899        int err;
3900
3901        err = ad198x_build_pcms(codec);
3902        if (err < 0)
3903                return err;
3904
3905        info = spec->pcm_rec + codec->num_pcms;
3906        codec->num_pcms++;
3907        info->name = "AD1984 Digital Mic";
3908        info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture;
3909        return 0;
3910}
3911
3912/* models */
3913enum {
3914        AD1984_AUTO,
3915        AD1984_BASIC,
3916        AD1984_THINKPAD,
3917        AD1984_DELL_DESKTOP,
3918        AD1984_MODELS
3919};
3920
3921static const char * const ad1984_models[AD1984_MODELS] = {
3922        [AD1984_AUTO]           = "auto",
3923        [AD1984_BASIC]          = "basic",
3924        [AD1984_THINKPAD]       = "thinkpad",
3925        [AD1984_DELL_DESKTOP]   = "dell_desktop",
3926};
3927
3928static const struct snd_pci_quirk ad1984_cfg_tbl[] = {
3929        /* Lenovo Thinkpad T61/X61 */
3930        SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
3931        SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
3932        SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
3933        {}
3934};
3935
3936static int patch_ad1984(struct hda_codec *codec)
3937{
3938        struct ad198x_spec *spec;
3939        int board_config, err;
3940
3941        board_config = snd_hda_check_board_config(codec, AD1984_MODELS,
3942                                                  ad1984_models, ad1984_cfg_tbl);
3943        if (board_config < 0) {
3944                printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
3945                       codec->chip_name);
3946                board_config = AD1984_AUTO;
3947        }
3948
3949        if (board_config == AD1984_AUTO)
3950                return ad1884_parse_auto_config(codec);
3951
3952        err = patch_ad1884_basic(codec);
3953        if (err < 0)
3954                return err;
3955        spec = codec->spec;
3956
3957        switch (board_config) {
3958        case AD1984_BASIC:
3959                /* additional digital mics */
3960                spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers;
3961                codec->patch_ops.build_pcms = ad1984_build_pcms;
3962                break;
3963        case AD1984_THINKPAD:
3964                if (codec->subsystem_id == 0x17aa20fb) {
3965                        /* Thinpad X300 does not have the ability to do SPDIF,
3966                           or attach to docking station to use SPDIF */
3967                        spec->multiout.dig_out_nid = 0;
3968                } else
3969                        spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3970                spec->input_mux = &ad1984_thinkpad_capture_source;
3971                spec->mixers[0] = ad1984_thinkpad_mixers;
3972                spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3973                spec->analog_beep = 1;
3974                break;
3975        case AD1984_DELL_DESKTOP:
3976                spec->multiout.dig_out_nid = 0;
3977                spec->input_mux = &ad1984_dell_desktop_capture_source;
3978                spec->mixers[0] = ad1984_dell_desktop_mixers;
3979                break;
3980        }
3981        return 0;
3982}
3983#else /* ENABLE_AD_STATIC_QUIRKS */
3984#define patch_ad1984    ad1884_parse_auto_config
3985#endif /* ENABLE_AD_STATIC_QUIRKS */
3986
3987
3988/*
3989 * AD1883 / AD1884A / AD1984A / AD1984B
3990 *
3991 * port-B (0x14) - front mic-in
3992 * port-E (0x1c) - rear mic-in
3993 * port-F (0x16) - CD / ext out
3994 * port-C (0x15) - rear line-in
3995 * port-D (0x12) - rear line-out
3996 * port-A (0x11) - front hp-out
3997 *
3998 * AD1984A = AD1884A + digital-mic
3999 * AD1883 = equivalent with AD1984A
4000 * AD1984B = AD1984A + extra SPDIF-out
4001 *
4002 * FIXME:
4003 * We share the single DAC for both HP and line-outs (see AD1884/1984).
4004 */
4005
4006#ifdef ENABLE_AD_STATIC_QUIRKS
4007static const hda_nid_t ad1884a_dac_nids[1] = {
4008        0x03,
4009};
4010
4011#define ad1884a_adc_nids        ad1884_adc_nids
4012#define ad1884a_capsrc_nids     ad1884_capsrc_nids
4013
4014#define AD1884A_SPDIF_OUT       0x02
4015
4016static const struct hda_input_mux ad1884a_capture_source = {
4017        .num_items = 5,
4018        .items = {
4019                { "Front Mic", 0x0 },
4020                { "Mic", 0x4 },
4021                { "Line", 0x1 },
4022                { "CD", 0x2 },
4023                { "Mix", 0x3 },
4024        },
4025};
4026
4027static const struct snd_kcontrol_new ad1884a_base_mixers[] = {
4028        HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4029        HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4030        HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4031        HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4032        HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4033        HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4034        HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4035        HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4036        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4037        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4038        HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4039        HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4040        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4041        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4042        HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
4043        HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
4044        HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4045        HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT),
4046        HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4047        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4048        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4049        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4050        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4051        {
4052                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4053                /* The multiple "Capture Source" controls confuse alsamixer
4054                 * So call somewhat different..
4055                 */
4056                /* .name = "Capture Source", */
4057                .name = "Input Source",
4058                .count = 2,
4059                .info = ad198x_mux_enum_info,
4060                .get = ad198x_mux_enum_get,
4061                .put = ad198x_mux_enum_put,
4062        },
4063        /* SPDIF controls */
4064        HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4065        {
4066                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4067                .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4068                /* identical with ad1983 */
4069                .info = ad1983_spdif_route_info,
4070                .get = ad1983_spdif_route_get,
4071                .put = ad1983_spdif_route_put,
4072        },
4073        { } /* end */
4074};
4075
4076/*
4077 * initialization verbs
4078 */
4079static const struct hda_verb ad1884a_init_verbs[] = {
4080        /* DACs; unmute as default */
4081        {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4082        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4083        /* Port-A (HP) mixer - route only from analog mixer */
4084        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4085        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4086        /* Port-A pin */
4087        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4088        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4089        /* Port-D (Line-out) mixer - route only from analog mixer */
4090        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4091        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4092        /* Port-D pin */
4093        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4094        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4095        /* Mono-out mixer - route only from analog mixer */
4096        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4097        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4098        /* Mono-out pin */
4099        {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4100        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4101        /* Port-B (front mic) pin */
4102        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4103        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4104        /* Port-C (rear line-in) pin */
4105        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4106        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4107        /* Port-E (rear mic) pin */
4108        {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4109        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4110        {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
4111        /* Port-F (CD) pin */
4112        {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4113        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4114        /* Analog mixer; mute as default */
4115        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4116        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4117        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4118        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4119        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
4120        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4121        /* Analog Mix output amp */
4122        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4123        /* capture sources */
4124        {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
4125        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4126        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4127        {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4128        /* SPDIF output amp */
4129        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
4130        { } /* end */
4131};
4132
4133#ifdef CONFIG_PM
4134static const struct hda_amp_list ad1884a_loopbacks[] = {
4135        { 0x20, HDA_INPUT, 0 }, /* Front Mic */
4136        { 0x20, HDA_INPUT, 1 }, /* Mic */
4137        { 0x20, HDA_INPUT, 2 }, /* CD */
4138        { 0x20, HDA_INPUT, 4 }, /* Docking */
4139        { } /* end */
4140};
4141#endif
4142
4143/*
4144 * Laptop model
4145 *
4146 * Port A: Headphone jack
4147 * Port B: MIC jack
4148 * Port C: Internal MIC
4149 * Port D: Dock Line Out (if enabled)
4150 * Port E: Dock Line In (if enabled)
4151 * Port F: Internal speakers
4152 */
4153
4154static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
4155                                        struct snd_ctl_elem_value *ucontrol)
4156{
4157        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4158        int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
4159        int mute = (!ucontrol->value.integer.value[0] &&
4160                    !ucontrol->value.integer.value[1]);
4161        /* toggle GPIO1 according to the mute state */
4162        snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
4163                            mute ? 0x02 : 0x0);
4164        return ret;
4165}
4166
4167static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
4168        HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4169        {
4170                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4171                .name = "Master Playback Switch",
4172                .subdevice = HDA_SUBDEV_AMP_FLAG,
4173                .info = snd_hda_mixer_amp_switch_info,
4174                .get = snd_hda_mixer_amp_switch_get,
4175                .put = ad1884a_mobile_master_sw_put,
4176                .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4177        },
4178        HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4179        HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4180        HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4181        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4182        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4183        HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4184        HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4185        HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4186        HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4187        HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4188        HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4189        HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4190        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4191        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4192        { } /* end */
4193};
4194
4195static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
4196        HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4197        /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4198        {
4199                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4200                .name = "Master Playback Switch",
4201                .subdevice = HDA_SUBDEV_AMP_FLAG,
4202                .info = snd_hda_mixer_amp_switch_info,
4203                .get = snd_hda_mixer_amp_switch_get,
4204                .put = ad1884a_mobile_master_sw_put,
4205                .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4206        },
4207        HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4208        HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4209        HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
4210        HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
4211        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4212        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4213        { } /* end */
4214};
4215
4216/* mute internal speaker if HP is plugged */
4217static void ad1884a_hp_automute(struct hda_codec *codec)
4218{
4219        unsigned int present;
4220
4221        present = snd_hda_jack_detect(codec, 0x11);
4222        snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4223                                 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4224        snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4225                            present ? 0x00 : 0x02);
4226}
4227
4228/* switch to external mic if plugged */
4229static void ad1884a_hp_automic(struct hda_codec *codec)
4230{
4231        unsigned int present;
4232
4233        present = snd_hda_jack_detect(codec, 0x14);
4234        snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
4235                            present ? 0 : 1);
4236}
4237
4238#define AD1884A_HP_EVENT                0x37
4239#define AD1884A_MIC_EVENT               0x36
4240
4241/* unsolicited event for HP jack sensing */
4242static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
4243{
4244        switch (res >> 26) {
4245        case AD1884A_HP_EVENT:
4246                ad1884a_hp_automute(codec);
4247                break;
4248        case AD1884A_MIC_EVENT:
4249                ad1884a_hp_automic(codec);
4250                break;
4251        }
4252}
4253
4254/* initialize jack-sensing, too */
4255static int ad1884a_hp_init(struct hda_codec *codec)
4256{
4257        ad198x_init(codec);
4258        ad1884a_hp_automute(codec);
4259        ad1884a_hp_automic(codec);
4260        return 0;
4261}
4262
4263/* mute internal speaker if HP or docking HP is plugged */
4264static void ad1884a_laptop_automute(struct hda_codec *codec)
4265{
4266        unsigned int present;
4267
4268        present = snd_hda_jack_detect(codec, 0x11);
4269        if (!present)
4270                present = snd_hda_jack_detect(codec, 0x12);
4271        snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
4272                                 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4273        snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
4274                            present ? 0x00 : 0x02);
4275}
4276
4277/* switch to external mic if plugged */
4278static void ad1884a_laptop_automic(struct hda_codec *codec)
4279{
4280        unsigned int idx;
4281
4282        if (snd_hda_jack_detect(codec, 0x14))
4283                idx = 0;
4284        else if (snd_hda_jack_detect(codec, 0x1c))
4285                idx = 4;
4286        else
4287                idx = 1;
4288        snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx);
4289}
4290
4291/* unsolicited event for HP jack sensing */
4292static void ad1884a_laptop_unsol_event(struct hda_codec *codec,
4293                                       unsigned int res)
4294{
4295        switch (res >> 26) {
4296        case AD1884A_HP_EVENT:
4297                ad1884a_laptop_automute(codec);
4298                break;
4299        case AD1884A_MIC_EVENT:
4300                ad1884a_laptop_automic(codec);
4301                break;
4302        }
4303}
4304
4305/* initialize jack-sensing, too */
4306static int ad1884a_laptop_init(struct hda_codec *codec)
4307{
4308        ad198x_init(codec);
4309        ad1884a_laptop_automute(codec);
4310        ad1884a_laptop_automic(codec);
4311        return 0;
4312}
4313
4314/* additional verbs for laptop model */
4315static const struct hda_verb ad1884a_laptop_verbs[] = {
4316        /* Port-A (HP) pin - always unmuted */
4317        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4318        /* Port-F (int speaker) mixer - route only from analog mixer */
4319        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4320        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4321        /* Port-F (int speaker) pin */
4322        {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4323        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4324        /* required for compaq 6530s/6531s speaker output */
4325        {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4326        /* Port-C pin - internal mic-in */
4327        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4328        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4329        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4330        /* Port-D (docking line-out) pin - default unmuted */
4331        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4332        /* analog mix */
4333        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4334        /* unsolicited event for pin-sense */
4335        {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4336        {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4337        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4338        {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4339        /* allow to touch GPIO1 (for mute control) */
4340        {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4341        {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4342        {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4343        { } /* end */
4344};
4345
4346static const struct hda_verb ad1884a_mobile_verbs[] = {
4347        /* DACs; unmute as default */
4348        {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4349        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4350        /* Port-A (HP) mixer - route only from analog mixer */
4351        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4352        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4353        /* Port-A pin */
4354        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4355        /* Port-A (HP) pin - always unmuted */
4356        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4357        /* Port-B (mic jack) pin */
4358        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4359        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4360        /* Port-C (int mic) pin */
4361        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4362        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4363        /* Port-F (int speaker) mixer - route only from analog mixer */
4364        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4365        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4366        /* Port-F pin */
4367        {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4368        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4369        /* Analog mixer; mute as default */
4370        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4371        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4372        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4373        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4374        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4375        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4376        /* Analog Mix output amp */
4377        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4378        /* capture sources */
4379        /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4380        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4381        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4382        {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4383        /* unsolicited event for pin-sense */
4384        {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4385        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4386        /* allow to touch GPIO1 (for mute control) */
4387        {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4388        {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4389        {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4390        { } /* end */
4391};
4392
4393/*
4394 * Thinkpad X300
4395 * 0x11 - HP
4396 * 0x12 - speaker
4397 * 0x14 - mic-in
4398 * 0x17 - built-in mic
4399 */
4400
4401static const struct hda_verb ad1984a_thinkpad_verbs[] = {
4402        /* HP unmute */
4403        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4404        /* analog mix */
4405        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4406        /* turn on EAPD */
4407        {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4408        /* unsolicited event for pin-sense */
4409        {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4410        /* internal mic - dmic */
4411        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4412        /* set magic COEFs for dmic */
4413        {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4414        {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4415        { } /* end */
4416};
4417
4418static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
4419        HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4420        HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4421        HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4422        HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4423        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4424        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4425        HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT),
4426        HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4427        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4428        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4429        {
4430                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4431                .name = "Capture Source",
4432                .info = ad198x_mux_enum_info,
4433                .get = ad198x_mux_enum_get,
4434                .put = ad198x_mux_enum_put,
4435        },
4436        { } /* end */
4437};
4438
4439static const struct hda_input_mux ad1984a_thinkpad_capture_source = {
4440        .num_items = 3,
4441        .items = {
4442                { "Mic", 0x0 },
4443                { "Internal Mic", 0x5 },
4444                { "Mix", 0x3 },
4445        },
4446};
4447
4448/* mute internal speaker if HP is plugged */
4449static void ad1984a_thinkpad_automute(struct hda_codec *codec)
4450{
4451        unsigned int present;
4452
4453        present = snd_hda_jack_detect(codec, 0x11);
4454        snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
4455                                 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4456}
4457
4458/* unsolicited event for HP jack sensing */
4459static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
4460                                         unsigned int res)
4461{
4462        if ((res >> 26) != AD1884A_HP_EVENT)
4463                return;
4464        ad1984a_thinkpad_automute(codec);
4465}
4466
4467/* initialize jack-sensing, too */
4468static int ad1984a_thinkpad_init(struct hda_codec *codec)
4469{
4470        ad198x_init(codec);
4471        ad1984a_thinkpad_automute(codec);
4472        return 0;
4473}
4474
4475/*
4476 * Precision R5500
4477 * 0x12 - HP/line-out
4478 * 0x13 - speaker (mono)
4479 * 0x15 - mic-in
4480 */
4481
4482static const struct hda_verb ad1984a_precision_verbs[] = {
4483        /* Unmute main output path */
4484        {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4485        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
4486        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
4487        /* Analog mixer; mute as default */
4488        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4489        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4490        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4491        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4492        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4493        /* Select mic as input */
4494        {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
4495        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
4496        /* Configure as mic */
4497        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4498        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
4499        /* HP unmute */
4500        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4501        /* turn on EAPD */
4502        {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
4503        /* unsolicited event for pin-sense */
4504        {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4505        { } /* end */
4506};
4507
4508static const struct snd_kcontrol_new ad1984a_precision_mixers[] = {
4509        HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4510        HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
4511        HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4512        HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4513        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4514        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4515        HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
4516        HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4517        HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
4518        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4519        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4520        { } /* end */
4521};
4522
4523
4524/* mute internal speaker if HP is plugged */
4525static void ad1984a_precision_automute(struct hda_codec *codec)
4526{
4527        unsigned int present;
4528
4529        present = snd_hda_jack_detect(codec, 0x12);
4530        snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
4531                                 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
4532}
4533
4534
4535/* unsolicited event for HP jack sensing */
4536static void ad1984a_precision_unsol_event(struct hda_codec *codec,
4537                                         unsigned int res)
4538{
4539        if ((res >> 26) != AD1884A_HP_EVENT)
4540                return;
4541        ad1984a_precision_automute(codec);
4542}
4543
4544/* initialize jack-sensing, too */
4545static int ad1984a_precision_init(struct hda_codec *codec)
4546{
4547        ad198x_init(codec);
4548        ad1984a_precision_automute(codec);
4549        return 0;
4550}
4551
4552
4553/*
4554 * HP Touchsmart
4555 * port-A (0x11)      - front hp-out
4556 * port-B (0x14)      - unused
4557 * port-C (0x15)      - unused
4558 * port-D (0x12)      - rear line out
4559 * port-E (0x1c)      - front mic-in
4560 * port-F (0x16)      - Internal speakers
4561 * digital-mic (0x17) - Internal mic
4562 */
4563
4564static const struct hda_verb ad1984a_touchsmart_verbs[] = {
4565        /* DACs; unmute as default */
4566        {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4567        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4568        /* Port-A (HP) mixer - route only from analog mixer */
4569        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4570        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4571        /* Port-A pin */
4572        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4573        /* Port-A (HP) pin - always unmuted */
4574        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4575        /* Port-E (int speaker) mixer - route only from analog mixer */
4576        {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4577        /* Port-E pin */
4578        {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4579        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4580        {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4581        /* Port-F (int speaker) mixer - route only from analog mixer */
4582        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4583        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4584        /* Port-F pin */
4585        {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4586        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4587        /* Analog mixer; mute as default */
4588        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4589        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4590        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4591        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4592        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4593        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4594        /* Analog Mix output amp */
4595        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4596        /* capture sources */
4597        /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4598        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4599        {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4600        {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4601        /* unsolicited event for pin-sense */
4602        {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4603        {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4604        /* allow to touch GPIO1 (for mute control) */
4605        {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4606        {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4607        {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4608        /* internal mic - dmic */
4609        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4610        /* set magic COEFs for dmic */
4611        {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4612        {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4613        { } /* end */
4614};
4615
4616static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4617        HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4618/*      HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4619        {
4620                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4621                .subdevice = HDA_SUBDEV_AMP_FLAG,
4622                .name = "Master Playback Switch",
4623                .info = snd_hda_mixer_amp_switch_info,
4624                .get = snd_hda_mixer_amp_switch_get,
4625                .put = ad1884a_mobile_master_sw_put,
4626                .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4627        },
4628        HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4629        HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4630        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4631        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4632        HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT),
4633        HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT),
4634        { } /* end */
4635};
4636
4637/* switch to external mic if plugged */
4638static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4639{
4640        if (snd_hda_jack_detect(codec, 0x1c))
4641                snd_hda_codec_write(codec, 0x0c, 0,
4642                                     AC_VERB_SET_CONNECT_SEL, 0x4);
4643        else
4644                snd_hda_codec_write(codec, 0x0c, 0,
4645                                     AC_VERB_SET_CONNECT_SEL, 0x5);
4646}
4647
4648
4649/* unsolicited event for HP jack sensing */
4650static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4651        unsigned int res)
4652{
4653        switch (res >> 26) {
4654        case AD1884A_HP_EVENT:
4655                ad1884a_hp_automute(codec);
4656                break;
4657        case AD1884A_MIC_EVENT:
4658                ad1984a_touchsmart_automic(codec);
4659                break;
4660        }
4661}
4662
4663/* initialize jack-sensing, too */
4664static int ad1984a_touchsmart_init(struct hda_codec *codec)
4665{
4666        ad198x_init(codec);
4667        ad1884a_hp_automute(codec);
4668        ad1984a_touchsmart_automic(codec);
4669        return 0;
4670}
4671
4672
4673/*
4674 */
4675
4676enum {
4677        AD1884A_AUTO,
4678        AD1884A_DESKTOP,
4679        AD1884A_LAPTOP,
4680        AD1884A_MOBILE,
4681        AD1884A_THINKPAD,
4682        AD1984A_TOUCHSMART,
4683        AD1984A_PRECISION,
4684        AD1884A_MODELS
4685};
4686
4687static const char * const ad1884a_models[AD1884A_MODELS] = {
4688        [AD1884A_AUTO]          = "auto",
4689        [AD1884A_DESKTOP]       = "desktop",
4690        [AD1884A_LAPTOP]        = "laptop",
4691        [AD1884A_MOBILE]        = "mobile",
4692        [AD1884A_THINKPAD]      = "thinkpad",
4693        [AD1984A_TOUCHSMART]    = "touchsmart",
4694        [AD1984A_PRECISION]     = "precision",
4695};
4696
4697static const struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4698        SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
4699        SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
4700        SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
4701        SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
4702        SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
4703        SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
4704        SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
4705        SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4706        SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4707        SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4708        SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4709        {}
4710};
4711
4712static int patch_ad1884a(struct hda_codec *codec)
4713{
4714        struct ad198x_spec *spec;
4715        int err, board_config;
4716
4717        board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
4718                                                  ad1884a_models,
4719                                                  ad1884a_cfg_tbl);
4720        if (board_config < 0) {
4721                printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4722                       codec->chip_name);
4723                board_config = AD1884A_AUTO;
4724        }
4725
4726        if (board_config == AD1884A_AUTO)
4727                return ad1884_parse_auto_config(codec);
4728
4729        err = alloc_ad_spec(codec);
4730        if (err < 0)
4731                return err;
4732        spec = codec->spec;
4733
4734        err = snd_hda_attach_beep_device(codec, 0x10);
4735        if (err < 0) {
4736                ad198x_free(codec);
4737                return err;
4738        }
4739        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4740
4741        spec->multiout.max_channels = 2;
4742        spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
4743        spec->multiout.dac_nids = ad1884a_dac_nids;
4744        spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
4745        spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
4746        spec->adc_nids = ad1884a_adc_nids;
4747        spec->capsrc_nids = ad1884a_capsrc_nids;
4748        spec->input_mux = &ad1884a_capture_source;
4749        spec->num_mixers = 1;
4750        spec->mixers[0] = ad1884a_base_mixers;
4751        spec->num_init_verbs = 1;
4752        spec->init_verbs[0] = ad1884a_init_verbs;
4753        spec->spdif_route = 0;
4754#ifdef CONFIG_PM
4755        spec->loopback.amplist = ad1884a_loopbacks;
4756#endif
4757        codec->patch_ops = ad198x_patch_ops;
4758
4759        /* override some parameters */
4760        switch (board_config) {
4761        case AD1884A_LAPTOP:
4762                spec->mixers[0] = ad1884a_laptop_mixers;
4763                spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
4764                spec->multiout.dig_out_nid = 0;
4765                codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event;
4766                codec->patch_ops.init = ad1884a_laptop_init;
4767                /* set the upper-limit for mixer amp to 0dB for avoiding the
4768                 * possible damage by overloading
4769                 */
4770                snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4771                                          (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4772                                          (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4773                                          (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4774                                          (1 << AC_AMPCAP_MUTE_SHIFT));
4775                break;
4776        case AD1884A_MOBILE:
4777                spec->mixers[0] = ad1884a_mobile_mixers;
4778                spec->init_verbs[0] = ad1884a_mobile_verbs;
4779                spec->multiout.dig_out_nid = 0;
4780                codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
4781                codec->patch_ops.init = ad1884a_hp_init;
4782                /* set the upper-limit for mixer amp to 0dB for avoiding the
4783                 * possible damage by overloading
4784                 */
4785                snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4786                                          (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4787                                          (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4788                                          (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4789                                          (1 << AC_AMPCAP_MUTE_SHIFT));
4790                break;
4791        case AD1884A_THINKPAD:
4792                spec->mixers[0] = ad1984a_thinkpad_mixers;
4793                spec->init_verbs[spec->num_init_verbs++] =
4794                        ad1984a_thinkpad_verbs;
4795                spec->multiout.dig_out_nid = 0;
4796                spec->input_mux = &ad1984a_thinkpad_capture_source;
4797                codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4798                codec->patch_ops.init = ad1984a_thinkpad_init;
4799                break;
4800        case AD1984A_PRECISION:
4801                spec->mixers[0] = ad1984a_precision_mixers;
4802                spec->init_verbs[spec->num_init_verbs++] =
4803                        ad1984a_precision_verbs;
4804                spec->multiout.dig_out_nid = 0;
4805                codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
4806                codec->patch_ops.init = ad1984a_precision_init;
4807                break;
4808        case AD1984A_TOUCHSMART:
4809                spec->mixers[0] = ad1984a_touchsmart_mixers;
4810                spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4811                spec->multiout.dig_out_nid = 0;
4812                codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4813                codec->patch_ops.init = ad1984a_touchsmart_init;
4814                /* set the upper-limit for mixer amp to 0dB for avoiding the
4815                 * possible damage by overloading
4816                 */
4817                snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4818                                          (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4819                                          (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4820                                          (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4821                                          (1 << AC_AMPCAP_MUTE_SHIFT));
4822                break;
4823        }
4824
4825        codec->no_trigger_sense = 1;
4826        codec->no_sticky_stream = 1;
4827
4828        return 0;
4829}
4830#else /* ENABLE_AD_STATIC_QUIRKS */
4831#define patch_ad1884a   ad1884_parse_auto_config
4832#endif /* ENABLE_AD_STATIC_QUIRKS */
4833
4834
4835/*
4836 * AD1882 / AD1882A
4837 *
4838 * port-A - front hp-out
4839 * port-B - front mic-in
4840 * port-C - rear line-in, shared surr-out (3stack)
4841 * port-D - rear line-out
4842 * port-E - rear mic-in, shared clfe-out (3stack)
4843 * port-F - rear surr-out (6stack)
4844 * port-G - rear clfe-out (6stack)
4845 */
4846
4847#ifdef ENABLE_AD_STATIC_QUIRKS
4848static const hda_nid_t ad1882_dac_nids[3] = {
4849        0x04, 0x03, 0x05
4850};
4851
4852static const hda_nid_t ad1882_adc_nids[2] = {
4853        0x08, 0x09,
4854};
4855
4856static const hda_nid_t ad1882_capsrc_nids[2] = {
4857        0x0c, 0x0d,
4858};
4859
4860#define AD1882_SPDIF_OUT        0x02
4861
4862/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
4863static const struct hda_input_mux ad1882_capture_source = {
4864        .num_items = 5,
4865        .items = {
4866                { "Front Mic", 0x1 },
4867                { "Mic", 0x4 },
4868                { "Line", 0x2 },
4869                { "CD", 0x3 },
4870                { "Mix", 0x7 },
4871        },
4872};
4873
4874/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
4875static const struct hda_input_mux ad1882a_capture_source = {
4876        .num_items = 5,
4877        .items = {
4878                { "Front Mic", 0x1 },
4879                { "Mic", 0x4},
4880                { "Line", 0x2 },
4881                { "Digital Mic", 0x06 },
4882                { "Mix", 0x7 },
4883        },
4884};
4885
4886static const struct snd_kcontrol_new ad1882_base_mixers[] = {
4887        HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
4888        HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
4889        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
4890        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
4891        HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
4892        HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
4893        HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
4894        HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
4895
4896        HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
4897        HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
4898        HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT),
4899        HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4900        HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4901        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
4902        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
4903        {
4904                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4905                /* The multiple "Capture Source" controls confuse alsamixer
4906                 * So call somewhat different..
4907                 */
4908                /* .name = "Capture Source", */
4909                .name = "Input Source",
4910                .count = 2,
4911                .info = ad198x_mux_enum_info,
4912                .get = ad198x_mux_enum_get,
4913                .put = ad198x_mux_enum_put,
4914        },
4915        /* SPDIF controls */
4916        HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
4917        {
4918                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4919                .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
4920                /* identical with ad1983 */
4921                .info = ad1983_spdif_route_info,
4922                .get = ad1983_spdif_route_get,
4923                .put = ad1983_spdif_route_put,
4924        },
4925        { } /* end */
4926};
4927
4928static const struct snd_kcontrol_new ad1882_loopback_mixers[] = {
4929        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4930        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4931        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
4932        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
4933        HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT),
4934        HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
4935        HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4936        HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4937        { } /* end */
4938};
4939
4940static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
4941        HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
4942        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
4943        HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
4944        HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
4945        HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
4946        HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
4947        HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
4948        HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
4949        HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT),
4950        { } /* end */
4951};
4952
4953static const struct snd_kcontrol_new ad1882_3stack_mixers[] = {
4954        HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
4955        HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
4956        HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
4957        {
4958                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4959                .name = "Channel Mode",
4960                .info = ad198x_ch_mode_info,
4961                .get = ad198x_ch_mode_get,
4962                .put = ad198x_ch_mode_put,
4963        },
4964        { } /* end */
4965};
4966
4967/* simple auto-mute control for AD1882 3-stack board */
4968#define AD1882_HP_EVENT 0x01
4969
4970static void ad1882_3stack_automute(struct hda_codec *codec)
4971{
4972        bool mute = snd_hda_jack_detect(codec, 0x11);
4973        snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4974                            mute ? 0 : PIN_OUT);
4975}
4976
4977static int ad1882_3stack_automute_init(struct hda_codec *codec)
4978{
4979        ad198x_init(codec);
4980        ad1882_3stack_automute(codec);
4981        return 0;
4982}
4983
4984static void ad1882_3stack_unsol_event(struct hda_codec *codec, unsigned int res)
4985{
4986        switch (res >> 26) {
4987        case AD1882_HP_EVENT:
4988                ad1882_3stack_automute(codec);
4989                break;
4990        }
4991}
4992
4993static const struct snd_kcontrol_new ad1882_6stack_mixers[] = {
4994        HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
4995        HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
4996        HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
4997        { } /* end */
4998};
4999
5000static const struct hda_verb ad1882_ch2_init[] = {
5001        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5002        {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5003        {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5004        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5005        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5006        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5007        { } /* end */
5008};
5009
5010static const struct hda_verb ad1882_ch4_init[] = {
5011        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5012        {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5013        {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5014        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5015        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5016        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5017        { } /* end */
5018};
5019
5020static const struct hda_verb ad1882_ch6_init[] = {
5021        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5022        {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5023        {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5024        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5025        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5026        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5027        { } /* end */
5028};
5029
5030static const struct hda_channel_mode ad1882_modes[3] = {
5031        { 2, ad1882_ch2_init },
5032        { 4, ad1882_ch4_init },
5033        { 6, ad1882_ch6_init },
5034};
5035
5036/*
5037 * initialization verbs
5038 */
5039static const struct hda_verb ad1882_init_verbs[] = {
5040        /* DACs; mute as default */
5041        {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5042        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5043        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
5044        /* Port-A (HP) mixer */
5045        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5046        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5047        /* Port-A pin */
5048        {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5049        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5050        /* HP selector - select DAC2 */
5051        {0x37, AC_VERB_SET_CONNECT_SEL, 0x1},
5052        /* Port-D (Line-out) mixer */
5053        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5054        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5055        /* Port-D pin */
5056        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5057        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5058        /* Mono-out mixer */
5059        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5060        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5061        /* Mono-out pin */
5062        {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5063        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5064        /* Port-B (front mic) pin */
5065        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5066        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5067        {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
5068        /* Port-C (line-in) pin */
5069        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
5070        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5071        {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
5072        /* Port-C mixer - mute as input */
5073        {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5074        {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5075        /* Port-E (mic-in) pin */
5076        {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
5077        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5078        {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */
5079        /* Port-E mixer - mute as input */
5080        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5081        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5082        /* Port-F (surround) */
5083        {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5084        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5085        /* Port-G (CLFE) */
5086        {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5087        {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
5088        /* Analog mixer; mute as default */
5089        /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */
5090        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
5091        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
5092        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
5093        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
5094        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
5095        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
5096        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
5097        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
5098        /* Analog Mix output amp */
5099        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
5100        /* SPDIF output selector */
5101        {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
5102        {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
5103        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
5104        { } /* end */
5105};
5106
5107static const struct hda_verb ad1882_3stack_automute_verbs[] = {
5108        {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1882_HP_EVENT},
5109        { } /* end */
5110};
5111
5112#ifdef CONFIG_PM
5113static const struct hda_amp_list ad1882_loopbacks[] = {
5114        { 0x20, HDA_INPUT, 0 }, /* Front Mic */
5115        { 0x20, HDA_INPUT, 1 }, /* Mic */
5116        { 0x20, HDA_INPUT, 4 }, /* Line */
5117        { 0x20, HDA_INPUT, 6 }, /* CD */
5118        { } /* end */
5119};
5120#endif
5121
5122/* models */
5123enum {
5124        AD1882_AUTO,
5125        AD1882_3STACK,
5126        AD1882_6STACK,
5127        AD1882_3STACK_AUTOMUTE,
5128        AD1882_MODELS
5129};
5130
5131static const char * const ad1882_models[AD1986A_MODELS] = {
5132        [AD1882_AUTO]           = "auto",
5133        [AD1882_3STACK]         = "3stack",
5134        [AD1882_6STACK]         = "6stack",
5135        [AD1882_3STACK_AUTOMUTE] = "3stack-automute",
5136};
5137#endif /* ENABLE_AD_STATIC_QUIRKS */
5138
5139static int ad1882_parse_auto_config(struct hda_codec *codec)
5140{
5141        struct ad198x_spec *spec;
5142        int err;
5143
5144        err = alloc_ad_spec(codec);
5145        if (err < 0)
5146                return err;
5147        spec = codec->spec;
5148
5149        spec->gen.mixer_nid = 0x20;
5150        spec->gen.mixer_merge_nid = 0x21;
5151        spec->gen.beep_nid = 0x10;
5152        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
5153        err = ad198x_parse_auto_config(codec);
5154        if (err < 0)
5155                goto error;
5156        err = ad1988_add_spdif_mux_ctl(codec);
5157        if (err < 0)
5158                goto error;
5159        return 0;
5160
5161 error:
5162        snd_hda_gen_free(codec);
5163        return err;
5164}
5165
5166#ifdef ENABLE_AD_STATIC_QUIRKS
5167static int patch_ad1882(struct hda_codec *codec)
5168{
5169        struct ad198x_spec *spec;
5170        int err, board_config;
5171
5172        board_config = snd_hda_check_board_config(codec, AD1882_MODELS,
5173                                                  ad1882_models, NULL);
5174        if (board_config < 0) {
5175                printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
5176                       codec->chip_name);
5177                board_config = AD1882_AUTO;
5178        }
5179
5180        if (board_config == AD1882_AUTO)
5181                return ad1882_parse_auto_config(codec);
5182
5183        err = alloc_ad_spec(codec);
5184        if (err < 0)
5185                return err;
5186        spec = codec->spec;
5187
5188        err = snd_hda_attach_beep_device(codec, 0x10);
5189        if (err < 0) {
5190                ad198x_free(codec);
5191                return err;
5192        }
5193        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
5194
5195        spec->multiout.max_channels = 6;
5196        spec->multiout.num_dacs = 3;
5197        spec->multiout.dac_nids = ad1882_dac_nids;
5198        spec->multiout.dig_out_nid = AD1882_SPDIF_OUT;
5199        spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids);
5200        spec->adc_nids = ad1882_adc_nids;
5201        spec->capsrc_nids = ad1882_capsrc_nids;
5202        if (codec->vendor_id == 0x11d41882)
5203                spec->input_mux = &ad1882_capture_source;
5204        else
5205                spec->input_mux = &ad1882a_capture_source;
5206        spec->num_mixers = 2;
5207        spec->mixers[0] = ad1882_base_mixers;
5208        if (codec->vendor_id == 0x11d41882)
5209                spec->mixers[1] = ad1882_loopback_mixers;
5210        else
5211                spec->mixers[1] = ad1882a_loopback_mixers;
5212        spec->num_init_verbs = 1;
5213        spec->init_verbs[0] = ad1882_init_verbs;
5214        spec->spdif_route = 0;
5215#ifdef CONFIG_PM
5216        spec->loopback.amplist = ad1882_loopbacks;
5217#endif
5218        spec->vmaster_nid = 0x04;
5219
5220        codec->patch_ops = ad198x_patch_ops;
5221
5222        /* override some parameters */
5223        switch (board_config) {
5224        default:
5225        case AD1882_3STACK:
5226        case AD1882_3STACK_AUTOMUTE:
5227                spec->num_mixers = 3;
5228                spec->mixers[2] = ad1882_3stack_mixers;
5229                spec->channel_mode = ad1882_modes;
5230                spec->num_channel_mode = ARRAY_SIZE(ad1882_modes);
5231                spec->need_dac_fix = 1;
5232                spec->multiout.max_channels = 2;
5233                spec->multiout.num_dacs = 1;
5234                if (board_config != AD1882_3STACK) {
5235                        spec->init_verbs[spec->num_init_verbs++] =
5236                                ad1882_3stack_automute_verbs;
5237                        codec->patch_ops.unsol_event = ad1882_3stack_unsol_event;
5238                        codec->patch_ops.init = ad1882_3stack_automute_init;
5239                }
5240                break;
5241        case AD1882_6STACK:
5242                spec->num_mixers = 3;
5243                spec->mixers[2] = ad1882_6stack_mixers;
5244                break;
5245        }
5246
5247        codec->no_trigger_sense = 1;
5248        codec->no_sticky_stream = 1;
5249
5250        return 0;
5251}
5252#else /* ENABLE_AD_STATIC_QUIRKS */
5253#define patch_ad1882    ad1882_parse_auto_config
5254#endif /* ENABLE_AD_STATIC_QUIRKS */
5255
5256
5257/*
5258 * patch entries
5259 */
5260static const struct hda_codec_preset snd_hda_preset_analog[] = {
5261        { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
5262        { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
5263        { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
5264        { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
5265        { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
5266        { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
5267        { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
5268        { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
5269        { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
5270        { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
5271        { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
5272        { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
5273        { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
5274        { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
5275        { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
5276        {} /* terminator */
5277};
5278
5279MODULE_ALIAS("snd-hda-codec-id:11d4*");
5280
5281MODULE_LICENSE("GPL");
5282MODULE_DESCRIPTION("Analog Devices HD-audio codec");
5283
5284static struct hda_codec_preset_list analog_list = {
5285        .preset = snd_hda_preset_analog,
5286        .owner = THIS_MODULE,
5287};
5288
5289static int __init patch_analog_init(void)
5290{
5291        return snd_hda_add_codec_preset(&analog_list);
5292}
5293
5294static void __exit patch_analog_exit(void)
5295{
5296        snd_hda_delete_codec_preset(&analog_list);
5297}
5298
5299module_init(patch_analog_init)
5300module_exit(patch_analog_exit)
5301