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