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