linux/sound/pci/hda/patch_via.c
<<
>>
Prefs
   1/*
   2 * Universal Interface for Intel High Definition Audio Codec
   3 *
   4 * HD audio interface patch for VIA VT1708 codec
   5 *
   6 * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
   7 *                    Takashi Iwai <tiwai@suse.de>
   8 *
   9 *  This driver is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License as published by
  11 *  the Free Software Foundation; either version 2 of the License, or
  12 *  (at your option) any later version.
  13 *
  14 *  This driver is distributed in the hope that it will be useful,
  15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 *  GNU General Public License for more details.
  18 *
  19 *  You should have received a copy of the GNU General Public License
  20 *  along with this program; if not, write to the Free Software
  21 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  22 */
  23
  24/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
  25/*                                                                           */
  26/* 2006-03-03  Lydia Wang  Create the basic patch to support VT1708 codec    */
  27/* 2006-03-14  Lydia Wang  Modify hard code for some pin widget nid          */
  28/* 2006-08-02  Lydia Wang  Add support to VT1709 codec                       */
  29/* 2006-09-08  Lydia Wang  Fix internal loopback recording source select bug */
  30/* 2007-09-12  Lydia Wang  Add EAPD enable during driver initialization      */
  31/* 2007-09-17  Lydia Wang  Add VT1708B codec support                        */
  32/*                                                                           */
  33/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  34
  35
  36#include <linux/init.h>
  37#include <linux/delay.h>
  38#include <linux/slab.h>
  39#include <sound/core.h>
  40#include "hda_codec.h"
  41#include "hda_local.h"
  42
  43
  44/* amp values */
  45#define AMP_VAL_IDX_SHIFT       19
  46#define AMP_VAL_IDX_MASK        (0x0f<<19)
  47
  48#define NUM_CONTROL_ALLOC       32
  49#define NUM_VERB_ALLOC          32
  50
  51/* Pin Widget NID */
  52#define VT1708_HP_NID           0x13
  53#define VT1708_DIGOUT_NID       0x14
  54#define VT1708_DIGIN_NID        0x16
  55#define VT1708_DIGIN_PIN        0x26
  56
  57#define VT1709_HP_DAC_NID       0x28
  58#define VT1709_DIGOUT_NID       0x13
  59#define VT1709_DIGIN_NID        0x17
  60#define VT1709_DIGIN_PIN        0x25
  61
  62#define VT1708B_HP_NID          0x25
  63#define VT1708B_DIGOUT_NID      0x12
  64#define VT1708B_DIGIN_NID       0x15
  65#define VT1708B_DIGIN_PIN       0x21
  66
  67#define IS_VT1708_VENDORID(x)           ((x) >= 0x11061708 && (x) <= 0x1106170b)
  68#define IS_VT1709_10CH_VENDORID(x)      ((x) >= 0x1106e710 && (x) <= 0x1106e713)
  69#define IS_VT1709_6CH_VENDORID(x)       ((x) >= 0x1106e714 && (x) <= 0x1106e717)
  70#define IS_VT1708B_8CH_VENDORID(x)      ((x) >= 0x1106e720 && (x) <= 0x1106e723)
  71#define IS_VT1708B_4CH_VENDORID(x)      ((x) >= 0x1106e724 && (x) <= 0x1106e727)
  72
  73
  74enum {
  75        VIA_CTL_WIDGET_VOL,
  76        VIA_CTL_WIDGET_MUTE,
  77};
  78
  79enum {
  80        AUTO_SEQ_FRONT,
  81        AUTO_SEQ_SURROUND,
  82        AUTO_SEQ_CENLFE,
  83        AUTO_SEQ_SIDE
  84};
  85
  86static struct snd_kcontrol_new vt1708_control_templates[] = {
  87        HDA_CODEC_VOLUME(NULL, 0, 0, 0),
  88        HDA_CODEC_MUTE(NULL, 0, 0, 0),
  89};
  90
  91
  92struct via_spec {
  93        /* codec parameterization */
  94        struct snd_kcontrol_new *mixers[3];
  95        unsigned int num_mixers;
  96
  97        struct hda_verb *init_verbs;
  98
  99        char *stream_name_analog;
 100        struct hda_pcm_stream *stream_analog_playback;
 101        struct hda_pcm_stream *stream_analog_capture;
 102
 103        char *stream_name_digital;
 104        struct hda_pcm_stream *stream_digital_playback;
 105        struct hda_pcm_stream *stream_digital_capture;
 106
 107        /* playback */
 108        struct hda_multi_out multiout;
 109
 110        /* capture */
 111        unsigned int num_adc_nids;
 112        hda_nid_t *adc_nids;
 113        hda_nid_t dig_in_nid;
 114
 115        /* capture source */
 116        const struct hda_input_mux *input_mux;
 117        unsigned int cur_mux[3];
 118
 119        /* PCM information */
 120        struct hda_pcm pcm_rec[2];
 121
 122        /* dynamic controls, init_verbs and input_mux */
 123        struct auto_pin_cfg autocfg;
 124        unsigned int num_kctl_alloc, num_kctl_used;
 125        struct snd_kcontrol_new *kctl_alloc;
 126        struct hda_input_mux private_imux;
 127        hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
 128
 129#ifdef CONFIG_SND_HDA_POWER_SAVE
 130        struct hda_loopback_check loopback;
 131#endif
 132};
 133
 134static hda_nid_t vt1708_adc_nids[2] = {
 135        /* ADC1-2 */
 136        0x15, 0x27
 137};
 138
 139static hda_nid_t vt1709_adc_nids[3] = {
 140        /* ADC1-2 */
 141        0x14, 0x15, 0x16
 142};
 143
 144static hda_nid_t vt1708B_adc_nids[2] = {
 145        /* ADC1-2 */
 146        0x13, 0x14
 147};
 148
 149/* add dynamic controls */
 150static int via_add_control(struct via_spec *spec, int type, const char *name,
 151                           unsigned long val)
 152{
 153        struct snd_kcontrol_new *knew;
 154
 155        if (spec->num_kctl_used >= spec->num_kctl_alloc) {
 156                int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
 157
 158                /* array + terminator */
 159                knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
 160                if (!knew)
 161                        return -ENOMEM;
 162                if (spec->kctl_alloc) {
 163                        memcpy(knew, spec->kctl_alloc,
 164                               sizeof(*knew) * spec->num_kctl_alloc);
 165                        kfree(spec->kctl_alloc);
 166                }
 167                spec->kctl_alloc = knew;
 168                spec->num_kctl_alloc = num;
 169        }
 170
 171        knew = &spec->kctl_alloc[spec->num_kctl_used];
 172        *knew = vt1708_control_templates[type];
 173        knew->name = kstrdup(name, GFP_KERNEL);
 174
 175        if (!knew->name)
 176                return -ENOMEM;
 177        knew->private_value = val;
 178        spec->num_kctl_used++;
 179        return 0;
 180}
 181
 182/* create input playback/capture controls for the given pin */
 183static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
 184                                const char *ctlname, int idx, int mix_nid)
 185{
 186        char name[32];
 187        int err;
 188
 189        sprintf(name, "%s Playback Volume", ctlname);
 190        err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
 191                              HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
 192        if (err < 0)
 193                return err;
 194        sprintf(name, "%s Playback Switch", ctlname);
 195        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
 196                              HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
 197        if (err < 0)
 198                return err;
 199        return 0;
 200}
 201
 202static void via_auto_set_output_and_unmute(struct hda_codec *codec,
 203                                           hda_nid_t nid, int pin_type,
 204                                           int dac_idx)
 205{
 206        /* set as output */
 207        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
 208                            pin_type);
 209        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
 210                            AMP_OUT_UNMUTE);
 211}
 212
 213
 214static void via_auto_init_multi_out(struct hda_codec *codec)
 215{
 216        struct via_spec *spec = codec->spec;
 217        int i;
 218
 219        for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
 220                hda_nid_t nid = spec->autocfg.line_out_pins[i];
 221                if (nid)
 222                        via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
 223        }
 224}
 225
 226static void via_auto_init_hp_out(struct hda_codec *codec)
 227{
 228        struct via_spec *spec = codec->spec;
 229        hda_nid_t pin;
 230
 231        pin = spec->autocfg.hp_pins[0];
 232        if (pin) /* connect to front */
 233                via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
 234}
 235
 236static void via_auto_init_analog_input(struct hda_codec *codec)
 237{
 238        struct via_spec *spec = codec->spec;
 239        int i;
 240
 241        for (i = 0; i < AUTO_PIN_LAST; i++) {
 242                hda_nid_t nid = spec->autocfg.input_pins[i];
 243
 244                snd_hda_codec_write(codec, nid, 0,
 245                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
 246                                    (i <= AUTO_PIN_FRONT_MIC ?
 247                                     PIN_VREF50 : PIN_IN));
 248
 249        }
 250}
 251/*
 252 * input MUX handling
 253 */
 254static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
 255                             struct snd_ctl_elem_info *uinfo)
 256{
 257        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 258        struct via_spec *spec = codec->spec;
 259        return snd_hda_input_mux_info(spec->input_mux, uinfo);
 260}
 261
 262static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
 263                            struct snd_ctl_elem_value *ucontrol)
 264{
 265        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 266        struct via_spec *spec = codec->spec;
 267        unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 268
 269        ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
 270        return 0;
 271}
 272
 273static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
 274                            struct snd_ctl_elem_value *ucontrol)
 275{
 276        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 277        struct via_spec *spec = codec->spec;
 278        unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 279        unsigned int vendor_id = codec->vendor_id;
 280
 281        /* AIW0  lydia 060801 add for correct sw0 input select */
 282        if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
 283                return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
 284                                             0x18, &spec->cur_mux[adc_idx]);
 285        else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
 286                  IS_VT1709_6CH_VENDORID(vendor_id)) && adc_idx == 0)
 287                return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
 288                                             0x19, &spec->cur_mux[adc_idx]);
 289        else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
 290                  IS_VT1708B_4CH_VENDORID(vendor_id)) && adc_idx == 0)
 291                return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
 292                                             0x17, &spec->cur_mux[adc_idx]);
 293        else
 294                return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
 295                                             spec->adc_nids[adc_idx],
 296                                             &spec->cur_mux[adc_idx]);
 297}
 298
 299/* capture mixer elements */
 300static struct snd_kcontrol_new vt1708_capture_mixer[] = {
 301        HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
 302        HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
 303        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
 304        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
 305        {
 306                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 307                /* The multiple "Capture Source" controls confuse alsamixer
 308                 * So call somewhat different..
 309                 */
 310                /* .name = "Capture Source", */
 311                .name = "Input Source",
 312                .count = 1,
 313                .info = via_mux_enum_info,
 314                .get = via_mux_enum_get,
 315                .put = via_mux_enum_put,
 316        },
 317        { } /* end */
 318};
 319/*
 320 * generic initialization of ADC, input mixers and output mixers
 321 */
 322static struct hda_verb vt1708_volume_init_verbs[] = {
 323        /*
 324         * Unmute ADC0-1 and set the default input to mic-in
 325         */
 326        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 327        {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 328
 329
 330        /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 331         * mixer widget
 332         */
 333        /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
 334        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 335        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 336        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 337        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 338        {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 339
 340        /*
 341         * Set up output mixers (0x19 - 0x1b)
 342         */
 343        /* set vol=0 to output mixers */
 344        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 345        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 346        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 347        
 348        /* Setup default input to PW4 */
 349        {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
 350        /* PW9 Output enable */
 351        {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
 352        { }
 353};
 354
 355static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
 356                                 struct hda_codec *codec,
 357                                 struct snd_pcm_substream *substream)
 358{
 359        struct via_spec *spec = codec->spec;
 360        return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
 361}
 362
 363static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 364                                    struct hda_codec *codec,
 365                                    unsigned int stream_tag,
 366                                    unsigned int format,
 367                                    struct snd_pcm_substream *substream)
 368{
 369        struct via_spec *spec = codec->spec;
 370        return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
 371                                                stream_tag, format, substream);
 372}
 373
 374static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
 375                                    struct hda_codec *codec,
 376                                    struct snd_pcm_substream *substream)
 377{
 378        struct via_spec *spec = codec->spec;
 379        return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
 380}
 381
 382/*
 383 * Digital out
 384 */
 385static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
 386                                     struct hda_codec *codec,
 387                                     struct snd_pcm_substream *substream)
 388{
 389        struct via_spec *spec = codec->spec;
 390        return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 391}
 392
 393static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 394                                      struct hda_codec *codec,
 395                                      struct snd_pcm_substream *substream)
 396{
 397        struct via_spec *spec = codec->spec;
 398        return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 399}
 400
 401static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 402                                        struct hda_codec *codec,
 403                                        unsigned int stream_tag,
 404                                        unsigned int format,
 405                                        struct snd_pcm_substream *substream)
 406{
 407        struct via_spec *spec = codec->spec;
 408        return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
 409                                             stream_tag, format, substream);
 410}
 411
 412/*
 413 * Analog capture
 414 */
 415static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
 416                                   struct hda_codec *codec,
 417                                   unsigned int stream_tag,
 418                                   unsigned int format,
 419                                   struct snd_pcm_substream *substream)
 420{
 421        struct via_spec *spec = codec->spec;
 422
 423        snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
 424                                   stream_tag, 0, format);
 425        return 0;
 426}
 427
 428static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 429                                   struct hda_codec *codec,
 430                                   struct snd_pcm_substream *substream)
 431{
 432        struct via_spec *spec = codec->spec;
 433        snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
 434                                   0, 0, 0);
 435        return 0;
 436}
 437
 438static struct hda_pcm_stream vt1708_pcm_analog_playback = {
 439        .substreams = 1,
 440        .channels_min = 2,
 441        .channels_max = 8,
 442        .nid = 0x10, /* NID to query formats and rates */
 443        .ops = {
 444                .open = via_playback_pcm_open,
 445                .prepare = via_playback_pcm_prepare,
 446                .cleanup = via_playback_pcm_cleanup
 447        },
 448};
 449
 450static struct hda_pcm_stream vt1708_pcm_analog_capture = {
 451        .substreams = 2,
 452        .channels_min = 2,
 453        .channels_max = 2,
 454        .nid = 0x15, /* NID to query formats and rates */
 455        .ops = {
 456                .prepare = via_capture_pcm_prepare,
 457                .cleanup = via_capture_pcm_cleanup
 458        },
 459};
 460
 461static struct hda_pcm_stream vt1708_pcm_digital_playback = {
 462        .substreams = 1,
 463        .channels_min = 2,
 464        .channels_max = 2,
 465        /* NID is set in via_build_pcms */
 466        .ops = {
 467                .open = via_dig_playback_pcm_open,
 468                .close = via_dig_playback_pcm_close,
 469                .prepare = via_dig_playback_pcm_prepare
 470        },
 471};
 472
 473static struct hda_pcm_stream vt1708_pcm_digital_capture = {
 474        .substreams = 1,
 475        .channels_min = 2,
 476        .channels_max = 2,
 477};
 478
 479static int via_build_controls(struct hda_codec *codec)
 480{
 481        struct via_spec *spec = codec->spec;
 482        int err;
 483        int i;
 484
 485        for (i = 0; i < spec->num_mixers; i++) {
 486                err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
 487                if (err < 0)
 488                        return err;
 489        }
 490
 491        if (spec->multiout.dig_out_nid) {
 492                err = snd_hda_create_spdif_out_ctls(codec,
 493                                                    spec->multiout.dig_out_nid);
 494                if (err < 0)
 495                        return err;
 496        }
 497        if (spec->dig_in_nid) {
 498                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
 499                if (err < 0)
 500                        return err;
 501        }
 502        return 0;
 503}
 504
 505static int via_build_pcms(struct hda_codec *codec)
 506{
 507        struct via_spec *spec = codec->spec;
 508        struct hda_pcm *info = spec->pcm_rec;
 509
 510        codec->num_pcms = 1;
 511        codec->pcm_info = info;
 512
 513        info->name = spec->stream_name_analog;
 514        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
 515        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
 516        info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
 517        info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
 518
 519        info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
 520                spec->multiout.max_channels;
 521
 522        if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
 523                codec->num_pcms++;
 524                info++;
 525                info->name = spec->stream_name_digital;
 526                if (spec->multiout.dig_out_nid) {
 527                        info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
 528                                *(spec->stream_digital_playback);
 529                        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
 530                                spec->multiout.dig_out_nid;
 531                }
 532                if (spec->dig_in_nid) {
 533                        info->stream[SNDRV_PCM_STREAM_CAPTURE] =
 534                                *(spec->stream_digital_capture);
 535                        info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
 536                                spec->dig_in_nid;
 537                }
 538        }
 539
 540        return 0;
 541}
 542
 543static void via_free(struct hda_codec *codec)
 544{
 545        struct via_spec *spec = codec->spec;
 546        unsigned int i;
 547
 548        if (!spec)
 549                return;
 550
 551        if (spec->kctl_alloc) {
 552                for (i = 0; i < spec->num_kctl_used; i++)
 553                        kfree(spec->kctl_alloc[i].name);
 554                kfree(spec->kctl_alloc);
 555        }
 556
 557        kfree(codec->spec);
 558}
 559
 560static int via_init(struct hda_codec *codec)
 561{
 562        struct via_spec *spec = codec->spec;
 563        snd_hda_sequence_write(codec, spec->init_verbs);
 564        /* Lydia Add for EAPD enable */
 565        if (!spec->dig_in_nid) { /* No Digital In connection */
 566                if (IS_VT1708_VENDORID(codec->vendor_id)) {
 567                        snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
 568                                            AC_VERB_SET_PIN_WIDGET_CONTROL,
 569                                            PIN_OUT);
 570                        snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
 571                                            AC_VERB_SET_EAPD_BTLENABLE, 0x02);
 572                } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
 573                           IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
 574                        snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
 575                                            AC_VERB_SET_PIN_WIDGET_CONTROL,
 576                                            PIN_OUT);
 577                        snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
 578                                            AC_VERB_SET_EAPD_BTLENABLE, 0x02);
 579                } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
 580                           IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
 581                        snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
 582                                            AC_VERB_SET_PIN_WIDGET_CONTROL,
 583                                            PIN_OUT);
 584                        snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
 585                                            AC_VERB_SET_EAPD_BTLENABLE, 0x02);
 586                }
 587        } else /* enable SPDIF-input pin */
 588                snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
 589                                    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
 590
 591        return 0;
 592}
 593
 594#ifdef CONFIG_SND_HDA_POWER_SAVE
 595static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
 596{
 597        struct via_spec *spec = codec->spec;
 598        return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
 599}
 600#endif
 601
 602/*
 603 */
 604static struct hda_codec_ops via_patch_ops = {
 605        .build_controls = via_build_controls,
 606        .build_pcms = via_build_pcms,
 607        .init = via_init,
 608        .free = via_free,
 609#ifdef CONFIG_SND_HDA_POWER_SAVE
 610        .check_power_status = via_check_power_status,
 611#endif
 612};
 613
 614/* fill in the dac_nids table from the parsed pin configuration */
 615static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
 616                                     const struct auto_pin_cfg *cfg)
 617{
 618        int i;
 619        hda_nid_t nid;
 620
 621        spec->multiout.num_dacs = cfg->line_outs;
 622
 623        spec->multiout.dac_nids = spec->private_dac_nids;
 624        
 625        for(i = 0; i < 4; i++) {
 626                nid = cfg->line_out_pins[i];
 627                if (nid) {
 628                        /* config dac list */
 629                        switch (i) {
 630                        case AUTO_SEQ_FRONT:
 631                                spec->multiout.dac_nids[i] = 0x10;
 632                                break;
 633                        case AUTO_SEQ_CENLFE:
 634                                spec->multiout.dac_nids[i] = 0x12;
 635                                break;
 636                        case AUTO_SEQ_SURROUND:
 637                                spec->multiout.dac_nids[i] = 0x13;
 638                                break;
 639                        case AUTO_SEQ_SIDE:
 640                                spec->multiout.dac_nids[i] = 0x11;
 641                                break;
 642                        }
 643                }
 644        }
 645
 646        return 0;
 647}
 648
 649/* add playback controls from the parsed DAC table */
 650static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
 651                                             const struct auto_pin_cfg *cfg)
 652{
 653        char name[32];
 654        static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
 655        hda_nid_t nid, nid_vol = 0;
 656        int i, err;
 657
 658        for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
 659                nid = cfg->line_out_pins[i];
 660
 661                if (!nid)
 662                        continue;
 663                
 664                if (i != AUTO_SEQ_FRONT)
 665                        nid_vol = 0x1b - i + 1;
 666
 667                if (i == AUTO_SEQ_CENLFE) {
 668                        /* Center/LFE */
 669                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
 670                                        "Center Playback Volume",
 671                                        HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
 672                                                            HDA_OUTPUT));
 673                        if (err < 0)
 674                                return err;
 675                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
 676                                              "LFE Playback Volume",
 677                                              HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
 678                                                                  HDA_OUTPUT));
 679                        if (err < 0)
 680                                return err;
 681                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
 682                                              "Center Playback Switch",
 683                                              HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
 684                                                                  HDA_OUTPUT));
 685                        if (err < 0)
 686                                return err;
 687                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
 688                                              "LFE Playback Switch",
 689                                              HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
 690                                                                  HDA_OUTPUT));
 691                        if (err < 0)
 692                                return err;
 693                } else if (i == AUTO_SEQ_FRONT){
 694                        /* add control to mixer index 0 */
 695                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
 696                                              "Master Front Playback Volume",
 697                                              HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
 698                                                                  HDA_INPUT));
 699                        if (err < 0)
 700                                return err;
 701                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
 702                                              "Master Front Playback Switch",
 703                                              HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
 704                                                                  HDA_INPUT));
 705                        if (err < 0)
 706                                return err;
 707                        
 708                        /* add control to PW3 */
 709                        sprintf(name, "%s Playback Volume", chname[i]);
 710                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
 711                                              HDA_COMPOSE_AMP_VAL(nid, 3, 0,
 712                                                                  HDA_OUTPUT));
 713                        if (err < 0)
 714                                return err;
 715                        sprintf(name, "%s Playback Switch", chname[i]);
 716                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
 717                                              HDA_COMPOSE_AMP_VAL(nid, 3, 0,
 718                                                                  HDA_OUTPUT));
 719                        if (err < 0)
 720                                return err;
 721                } else {
 722                        sprintf(name, "%s Playback Volume", chname[i]);
 723                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
 724                                              HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
 725                                                                  HDA_OUTPUT));
 726                        if (err < 0)
 727                                return err;
 728                        sprintf(name, "%s Playback Switch", chname[i]);
 729                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
 730                                              HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
 731                                                                  HDA_OUTPUT));
 732                        if (err < 0)
 733                                return err;
 734                }
 735        }
 736
 737        return 0;
 738}
 739
 740static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 741{
 742        int err;
 743
 744        if (!pin)
 745                return 0;
 746
 747        spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
 748
 749        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
 750                              "Headphone Playback Volume",
 751                              HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
 752        if (err < 0)
 753                return err;
 754        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
 755                              "Headphone Playback Switch",
 756                              HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
 757        if (err < 0)
 758                return err;
 759
 760        return 0;
 761}
 762
 763/* create playback/capture controls for input pins */
 764static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
 765                                                const struct auto_pin_cfg *cfg)
 766{
 767        static char *labels[] = {
 768                "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
 769        };
 770        struct hda_input_mux *imux = &spec->private_imux;
 771        int i, err, idx = 0;
 772
 773        /* for internal loopback recording select */
 774        imux->items[imux->num_items].label = "Stereo Mixer";
 775        imux->items[imux->num_items].index = idx;
 776        imux->num_items++;
 777
 778        for (i = 0; i < AUTO_PIN_LAST; i++) {
 779                if (!cfg->input_pins[i])
 780                        continue;
 781
 782                switch (cfg->input_pins[i]) {
 783                case 0x1d: /* Mic */
 784                        idx = 2;
 785                        break;
 786                                
 787                case 0x1e: /* Line In */
 788                        idx = 3;
 789                        break;
 790
 791                case 0x21: /* Front Mic */
 792                        idx = 4;
 793                        break;
 794
 795                case 0x24: /* CD */
 796                        idx = 1;
 797                        break;
 798                }
 799                err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
 800                                           idx, 0x17);
 801                if (err < 0)
 802                        return err;
 803                imux->items[imux->num_items].label = labels[i];
 804                imux->items[imux->num_items].index = idx;
 805                imux->num_items++;
 806        }
 807        return 0;
 808}
 809
 810#ifdef CONFIG_SND_HDA_POWER_SAVE
 811static struct hda_amp_list vt1708_loopbacks[] = {
 812        { 0x17, HDA_INPUT, 1 },
 813        { 0x17, HDA_INPUT, 2 },
 814        { 0x17, HDA_INPUT, 3 },
 815        { 0x17, HDA_INPUT, 4 },
 816        { } /* end */
 817};
 818#endif
 819
 820static int vt1708_parse_auto_config(struct hda_codec *codec)
 821{
 822        struct via_spec *spec = codec->spec;
 823        int err;
 824
 825        err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
 826        if (err < 0)
 827                return err;
 828        err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
 829        if (err < 0)
 830                return err;
 831        if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
 832                return 0; /* can't find valid BIOS pin config */
 833
 834        err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
 835        if (err < 0)
 836                return err;
 837        err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
 838        if (err < 0)
 839                return err;
 840        err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
 841        if (err < 0)
 842                return err;
 843
 844        spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 845
 846        if (spec->autocfg.dig_out_pin)
 847                spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
 848        if (spec->autocfg.dig_in_pin)
 849                spec->dig_in_nid = VT1708_DIGIN_NID;
 850
 851        if (spec->kctl_alloc)
 852                spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 853
 854        spec->init_verbs = vt1708_volume_init_verbs;    
 855
 856        spec->input_mux = &spec->private_imux;
 857
 858        return 1;
 859}
 860
 861/* init callback for auto-configuration model -- overriding the default init */
 862static int via_auto_init(struct hda_codec *codec)
 863{
 864        via_init(codec);
 865        via_auto_init_multi_out(codec);
 866        via_auto_init_hp_out(codec);
 867        via_auto_init_analog_input(codec);
 868        return 0;
 869}
 870
 871static int patch_vt1708(struct hda_codec *codec)
 872{
 873        struct via_spec *spec;
 874        int err;
 875
 876        /* create a codec specific record */
 877        spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
 878        if (spec == NULL)
 879                return -ENOMEM;
 880
 881        codec->spec = spec;
 882
 883        /* automatic parse from the BIOS config */
 884        err = vt1708_parse_auto_config(codec);
 885        if (err < 0) {
 886                via_free(codec);
 887                return err;
 888        } else if (!err) {
 889                printk(KERN_INFO "hda_codec: Cannot set up configuration "
 890                       "from BIOS.  Using genenic mode...\n");
 891        }
 892
 893        
 894        spec->stream_name_analog = "VT1708 Analog";
 895        spec->stream_analog_playback = &vt1708_pcm_analog_playback;
 896        spec->stream_analog_capture = &vt1708_pcm_analog_capture;
 897
 898        spec->stream_name_digital = "VT1708 Digital";
 899        spec->stream_digital_playback = &vt1708_pcm_digital_playback;
 900        spec->stream_digital_capture = &vt1708_pcm_digital_capture;
 901
 902        
 903        if (!spec->adc_nids && spec->input_mux) {
 904                spec->adc_nids = vt1708_adc_nids;
 905                spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
 906                spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
 907                spec->num_mixers++;
 908        }
 909
 910        codec->patch_ops = via_patch_ops;
 911
 912        codec->patch_ops.init = via_auto_init;
 913#ifdef CONFIG_SND_HDA_POWER_SAVE
 914        spec->loopback.amplist = vt1708_loopbacks;
 915#endif
 916
 917        return 0;
 918}
 919
 920/* capture mixer elements */
 921static struct snd_kcontrol_new vt1709_capture_mixer[] = {
 922        HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
 923        HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
 924        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
 925        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
 926        HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
 927        HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
 928        {
 929                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 930                /* The multiple "Capture Source" controls confuse alsamixer
 931                 * So call somewhat different..
 932                 */
 933                /* .name = "Capture Source", */
 934                .name = "Input Source",
 935                .count = 1,
 936                .info = via_mux_enum_info,
 937                .get = via_mux_enum_get,
 938                .put = via_mux_enum_put,
 939        },
 940        { } /* end */
 941};
 942
 943/*
 944 * generic initialization of ADC, input mixers and output mixers
 945 */
 946static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
 947        /*
 948         * Unmute ADC0-2 and set the default input to mic-in
 949         */
 950        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 951        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 952        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 953
 954
 955        /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 956         * mixer widget
 957         */
 958        /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
 959        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 960        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 961        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 962        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 963        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 964
 965        /*
 966         * Set up output selector (0x1a, 0x1b, 0x29)
 967         */
 968        /* set vol=0 to output mixers */
 969        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 970        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 971        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 972
 973        /*
 974         *  Unmute PW3 and PW4
 975         */
 976        {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 977        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 978
 979        /* Set input of PW4 as AOW4 */
 980        {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
 981        /* PW9 Output enable */
 982        {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
 983        { }
 984};
 985
 986static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
 987        .substreams = 1,
 988        .channels_min = 2,
 989        .channels_max = 10,
 990        .nid = 0x10, /* NID to query formats and rates */
 991        .ops = {
 992                .open = via_playback_pcm_open,
 993                .prepare = via_playback_pcm_prepare,
 994                .cleanup = via_playback_pcm_cleanup
 995        },
 996};
 997
 998static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
 999        .substreams = 1,
1000        .channels_min = 2,
1001        .channels_max = 6,
1002        .nid = 0x10, /* NID to query formats and rates */
1003        .ops = {
1004                .open = via_playback_pcm_open,
1005                .prepare = via_playback_pcm_prepare,
1006                .cleanup = via_playback_pcm_cleanup
1007        },
1008};
1009
1010static struct hda_pcm_stream vt1709_pcm_analog_capture = {
1011        .substreams = 2,
1012        .channels_min = 2,
1013        .channels_max = 2,
1014        .nid = 0x14, /* NID to query formats and rates */
1015        .ops = {
1016                .prepare = via_capture_pcm_prepare,
1017                .cleanup = via_capture_pcm_cleanup
1018        },
1019};
1020
1021static struct hda_pcm_stream vt1709_pcm_digital_playback = {
1022        .substreams = 1,
1023        .channels_min = 2,
1024        .channels_max = 2,
1025        /* NID is set in via_build_pcms */
1026        .ops = {
1027                .open = via_dig_playback_pcm_open,
1028                .close = via_dig_playback_pcm_close
1029        },
1030};
1031
1032static struct hda_pcm_stream vt1709_pcm_digital_capture = {
1033        .substreams = 1,
1034        .channels_min = 2,
1035        .channels_max = 2,
1036};
1037
1038static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1039                                     const struct auto_pin_cfg *cfg)
1040{
1041        int i;
1042        hda_nid_t nid;
1043
1044        if (cfg->line_outs == 4)  /* 10 channels */
1045                spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
1046        else if (cfg->line_outs == 3) /* 6 channels */
1047                spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
1048
1049        spec->multiout.dac_nids = spec->private_dac_nids;
1050
1051        if (cfg->line_outs == 4) { /* 10 channels */
1052                for (i = 0; i < cfg->line_outs; i++) {
1053                        nid = cfg->line_out_pins[i];
1054                        if (nid) {
1055                                /* config dac list */
1056                                switch (i) {
1057                                case AUTO_SEQ_FRONT:
1058                                        /* AOW0 */
1059                                        spec->multiout.dac_nids[i] = 0x10;
1060                                        break;
1061                                case AUTO_SEQ_CENLFE:
1062                                        /* AOW2 */
1063                                        spec->multiout.dac_nids[i] = 0x12;
1064                                        break;
1065                                case AUTO_SEQ_SURROUND:
1066                                        /* AOW3 */
1067                                        spec->multiout.dac_nids[i] = 0x27;
1068                                        break;
1069                                case AUTO_SEQ_SIDE:
1070                                        /* AOW1 */
1071                                        spec->multiout.dac_nids[i] = 0x11;
1072                                        break;
1073                                default:
1074                                        break;
1075                                }
1076                        }
1077                }
1078                spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1079
1080        } else if (cfg->line_outs == 3) { /* 6 channels */
1081                for(i = 0; i < cfg->line_outs; i++) {
1082                        nid = cfg->line_out_pins[i];
1083                        if (nid) {
1084                                /* config dac list */
1085                                switch(i) {
1086                                case AUTO_SEQ_FRONT:
1087                                        /* AOW0 */
1088                                        spec->multiout.dac_nids[i] = 0x10;
1089                                        break;
1090                                case AUTO_SEQ_CENLFE:
1091                                        /* AOW2 */
1092                                        spec->multiout.dac_nids[i] = 0x12;
1093                                        break;
1094                                case AUTO_SEQ_SURROUND:
1095                                        /* AOW1 */
1096                                        spec->multiout.dac_nids[i] = 0x11;
1097                                        break;
1098                                default:
1099                                        break;
1100                                }
1101                        }
1102                }
1103        }
1104
1105        return 0;
1106}
1107
1108/* add playback controls from the parsed DAC table */
1109static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1110                                             const struct auto_pin_cfg *cfg)
1111{
1112        char name[32];
1113        static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1114        hda_nid_t nid = 0;
1115        int i, err;
1116
1117        for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1118                nid = cfg->line_out_pins[i];
1119
1120                if (!nid)       
1121                        continue;
1122
1123                if (i == AUTO_SEQ_CENLFE) {
1124                        /* Center/LFE */
1125                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1126                                              "Center Playback Volume",
1127                                              HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1128                                                                  HDA_OUTPUT));
1129                        if (err < 0)
1130                                return err;
1131                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1132                                              "LFE Playback Volume",
1133                                              HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1134                                                                  HDA_OUTPUT));
1135                        if (err < 0)
1136                                return err;
1137                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1138                                              "Center Playback Switch",
1139                                              HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1140                                                                  HDA_OUTPUT));
1141                        if (err < 0)
1142                                return err;
1143                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1144                                              "LFE Playback Switch",
1145                                              HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1146                                                                  HDA_OUTPUT));
1147                        if (err < 0)
1148                                return err;
1149                } else if (i == AUTO_SEQ_FRONT){
1150                        /* add control to mixer index 0 */
1151                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1152                                              "Master Front Playback Volume",
1153                                              HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1154                                                                  HDA_INPUT));
1155                        if (err < 0)
1156                                return err;
1157                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1158                                              "Master Front Playback Switch",
1159                                              HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1160                                                                  HDA_INPUT));
1161                        if (err < 0)
1162                                return err;
1163                        
1164                        /* add control to PW3 */
1165                        sprintf(name, "%s Playback Volume", chname[i]);
1166                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1167                                              HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1168                                                                  HDA_OUTPUT));
1169                        if (err < 0)
1170                                return err;
1171                        sprintf(name, "%s Playback Switch", chname[i]);
1172                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1173                                              HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1174                                                                  HDA_OUTPUT));
1175                        if (err < 0)
1176                                return err;
1177                } else if (i == AUTO_SEQ_SURROUND) {
1178                        sprintf(name, "%s Playback Volume", chname[i]);
1179                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1180                                              HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1181                                                                  HDA_OUTPUT));
1182                        if (err < 0)
1183                                return err;
1184                        sprintf(name, "%s Playback Switch", chname[i]);
1185                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1186                                              HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1187                                                                  HDA_OUTPUT));
1188                        if (err < 0)
1189                                return err;
1190                } else if (i == AUTO_SEQ_SIDE) {
1191                        sprintf(name, "%s Playback Volume", chname[i]);
1192                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1193                                              HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1194                                                                  HDA_OUTPUT));
1195                        if (err < 0)
1196                                return err;
1197                        sprintf(name, "%s Playback Switch", chname[i]);
1198                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1199                                              HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1200                                                                  HDA_OUTPUT));
1201                        if (err < 0)
1202                                return err;
1203                }
1204        }
1205
1206        return 0;
1207}
1208
1209static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1210{
1211        int err;
1212
1213        if (!pin)
1214                return 0;
1215
1216        if (spec->multiout.num_dacs == 5) /* 10 channels */
1217                spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1218        else if (spec->multiout.num_dacs == 3) /* 6 channels */
1219                spec->multiout.hp_nid = 0;
1220
1221        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1222                              "Headphone Playback Volume",
1223                              HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1224        if (err < 0)
1225                return err;
1226        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1227                              "Headphone Playback Switch",
1228                              HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1229        if (err < 0)
1230                return err;
1231
1232        return 0;
1233}
1234
1235/* create playback/capture controls for input pins */
1236static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1237                                                const struct auto_pin_cfg *cfg)
1238{
1239        static char *labels[] = {
1240                "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1241        };
1242        struct hda_input_mux *imux = &spec->private_imux;
1243        int i, err, idx = 0;
1244
1245        /* for internal loopback recording select */
1246        imux->items[imux->num_items].label = "Stereo Mixer";
1247        imux->items[imux->num_items].index = idx;
1248        imux->num_items++;
1249
1250        for (i = 0; i < AUTO_PIN_LAST; i++) {
1251                if (!cfg->input_pins[i])
1252                        continue;
1253
1254                switch (cfg->input_pins[i]) {
1255                case 0x1d: /* Mic */
1256                        idx = 2;
1257                        break;
1258                                
1259                case 0x1e: /* Line In */
1260                        idx = 3;
1261                        break;
1262
1263                case 0x21: /* Front Mic */
1264                        idx = 4;
1265                        break;
1266
1267                case 0x23: /* CD */
1268                        idx = 1;
1269                        break;
1270                }
1271                err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1272                                           idx, 0x18);
1273                if (err < 0)
1274                        return err;
1275                imux->items[imux->num_items].label = labels[i];
1276                imux->items[imux->num_items].index = idx;
1277                imux->num_items++;
1278        }
1279        return 0;
1280}
1281
1282static int vt1709_parse_auto_config(struct hda_codec *codec)
1283{
1284        struct via_spec *spec = codec->spec;
1285        int err;
1286
1287        err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1288        if (err < 0)
1289                return err;
1290        err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1291        if (err < 0)
1292                return err;
1293        if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1294                return 0; /* can't find valid BIOS pin config */
1295
1296        err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1297        if (err < 0)
1298                return err;
1299        err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1300        if (err < 0)
1301                return err;
1302        err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1303        if (err < 0)
1304                return err;
1305
1306        spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1307
1308        if (spec->autocfg.dig_out_pin)
1309                spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1310        if (spec->autocfg.dig_in_pin)
1311                spec->dig_in_nid = VT1709_DIGIN_NID;
1312
1313        if (spec->kctl_alloc)
1314                spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1315
1316        spec->input_mux = &spec->private_imux;
1317
1318        return 1;
1319}
1320
1321#ifdef CONFIG_SND_HDA_POWER_SAVE
1322static struct hda_amp_list vt1709_loopbacks[] = {
1323        { 0x18, HDA_INPUT, 1 },
1324        { 0x18, HDA_INPUT, 2 },
1325        { 0x18, HDA_INPUT, 3 },
1326        { 0x18, HDA_INPUT, 4 },
1327        { } /* end */
1328};
1329#endif
1330
1331static int patch_vt1709_10ch(struct hda_codec *codec)
1332{
1333        struct via_spec *spec;
1334        int err;
1335
1336        /* create a codec specific record */
1337        spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1338        if (spec == NULL)
1339                return -ENOMEM;
1340
1341        codec->spec = spec;
1342
1343        err = vt1709_parse_auto_config(codec);
1344        if (err < 0) {
1345                via_free(codec);
1346                return err;
1347        } else if (!err) {
1348                printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1349                       "Using genenic mode...\n");
1350        }
1351
1352        spec->init_verbs = vt1709_10ch_volume_init_verbs;       
1353
1354        spec->stream_name_analog = "VT1709 Analog";
1355        spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1356        spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1357
1358        spec->stream_name_digital = "VT1709 Digital";
1359        spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1360        spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1361
1362        
1363        if (!spec->adc_nids && spec->input_mux) {
1364                spec->adc_nids = vt1709_adc_nids;
1365                spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1366                spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1367                spec->num_mixers++;
1368        }
1369
1370        codec->patch_ops = via_patch_ops;
1371
1372        codec->patch_ops.init = via_auto_init;
1373#ifdef CONFIG_SND_HDA_POWER_SAVE
1374        spec->loopback.amplist = vt1709_loopbacks;
1375#endif
1376
1377        return 0;
1378}
1379/*
1380 * generic initialization of ADC, input mixers and output mixers
1381 */
1382static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1383        /*
1384         * Unmute ADC0-2 and set the default input to mic-in
1385         */
1386        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1387        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1388        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1389
1390
1391        /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1392         * mixer widget
1393         */
1394        /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1395        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1396        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1397        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1398        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1399        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1400
1401        /*
1402         * Set up output selector (0x1a, 0x1b, 0x29)
1403         */
1404        /* set vol=0 to output mixers */
1405        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1406        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1407        {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1408
1409        /*
1410         *  Unmute PW3 and PW4
1411         */
1412        {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1413        {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1414
1415        /* Set input of PW4 as MW0 */
1416        {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1417        /* PW9 Output enable */
1418        {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1419        { }
1420};
1421
1422static int patch_vt1709_6ch(struct hda_codec *codec)
1423{
1424        struct via_spec *spec;
1425        int err;
1426
1427        /* create a codec specific record */
1428        spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1429        if (spec == NULL)
1430                return -ENOMEM;
1431
1432        codec->spec = spec;
1433
1434        err = vt1709_parse_auto_config(codec);
1435        if (err < 0) {
1436                via_free(codec);
1437                return err;
1438        } else if (!err) {
1439                printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1440                       "Using genenic mode...\n");
1441        }
1442
1443        spec->init_verbs = vt1709_6ch_volume_init_verbs;        
1444
1445        spec->stream_name_analog = "VT1709 Analog";
1446        spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1447        spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1448
1449        spec->stream_name_digital = "VT1709 Digital";
1450        spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1451        spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1452
1453        
1454        if (!spec->adc_nids && spec->input_mux) {
1455                spec->adc_nids = vt1709_adc_nids;
1456                spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1457                spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1458                spec->num_mixers++;
1459        }
1460
1461        codec->patch_ops = via_patch_ops;
1462
1463        codec->patch_ops.init = via_auto_init;
1464#ifdef CONFIG_SND_HDA_POWER_SAVE
1465        spec->loopback.amplist = vt1709_loopbacks;
1466#endif
1467        return 0;
1468}
1469
1470/* capture mixer elements */
1471static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
1472        HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1473        HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1474        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1475        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1476        {
1477                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1478                /* The multiple "Capture Source" controls confuse alsamixer
1479                 * So call somewhat different..
1480                 */
1481                /* .name = "Capture Source", */
1482                .name = "Input Source",
1483                .count = 1,
1484                .info = via_mux_enum_info,
1485                .get = via_mux_enum_get,
1486                .put = via_mux_enum_put,
1487        },
1488        { } /* end */
1489};
1490/*
1491 * generic initialization of ADC, input mixers and output mixers
1492 */
1493static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1494        /*
1495         * Unmute ADC0-1 and set the default input to mic-in
1496         */
1497        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1498        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1499
1500
1501        /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1502         * mixer widget
1503         */
1504        /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1505        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1506        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1507        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1508        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1509        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1510
1511        /*
1512         * Set up output mixers
1513         */
1514        /* set vol=0 to output mixers */
1515        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1516        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1517        {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1518
1519        /* Setup default input to PW4 */
1520        {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1521        /* PW9 Output enable */
1522        {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1523        /* PW10 Input enable */
1524        {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1525        { }
1526};
1527
1528static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1529        /*
1530         * Unmute ADC0-1 and set the default input to mic-in
1531         */
1532        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1533        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1534
1535
1536        /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1537         * mixer widget
1538         */
1539        /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1540        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1541        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1542        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1543        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1544        {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1545
1546        /*
1547         * Set up output mixers
1548         */
1549        /* set vol=0 to output mixers */
1550        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1551        {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1552        {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1553
1554        /* Setup default input of PW4 to MW0 */
1555        {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1556        /* PW9 Output enable */
1557        {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1558        /* PW10 Input enable */
1559        {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1560        { }
1561};
1562
1563static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
1564        .substreams = 1,
1565        .channels_min = 2,
1566        .channels_max = 8,
1567        .nid = 0x10, /* NID to query formats and rates */
1568        .ops = {
1569                .open = via_playback_pcm_open,
1570                .prepare = via_playback_pcm_prepare,
1571                .cleanup = via_playback_pcm_cleanup
1572        },
1573};
1574
1575static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
1576        .substreams = 1,
1577        .channels_min = 2,
1578        .channels_max = 4,
1579        .nid = 0x10, /* NID to query formats and rates */
1580        .ops = {
1581                .open = via_playback_pcm_open,
1582                .prepare = via_playback_pcm_prepare,
1583                .cleanup = via_playback_pcm_cleanup
1584        },
1585};
1586
1587static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
1588        .substreams = 2,
1589        .channels_min = 2,
1590        .channels_max = 2,
1591        .nid = 0x13, /* NID to query formats and rates */
1592        .ops = {
1593                .prepare = via_capture_pcm_prepare,
1594                .cleanup = via_capture_pcm_cleanup
1595        },
1596};
1597
1598static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
1599        .substreams = 1,
1600        .channels_min = 2,
1601        .channels_max = 2,
1602        /* NID is set in via_build_pcms */
1603        .ops = {
1604                .open = via_dig_playback_pcm_open,
1605                .close = via_dig_playback_pcm_close,
1606                .prepare = via_dig_playback_pcm_prepare
1607        },
1608};
1609
1610static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
1611        .substreams = 1,
1612        .channels_min = 2,
1613        .channels_max = 2,
1614};
1615
1616/* fill in the dac_nids table from the parsed pin configuration */
1617static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
1618                                     const struct auto_pin_cfg *cfg)
1619{
1620        int i;
1621        hda_nid_t nid;
1622
1623        spec->multiout.num_dacs = cfg->line_outs;
1624
1625        spec->multiout.dac_nids = spec->private_dac_nids;
1626
1627        for (i = 0; i < 4; i++) {
1628                nid = cfg->line_out_pins[i];
1629                if (nid) {
1630                        /* config dac list */
1631                        switch (i) {
1632                        case AUTO_SEQ_FRONT:
1633                                spec->multiout.dac_nids[i] = 0x10;
1634                                break;
1635                        case AUTO_SEQ_CENLFE:
1636                                spec->multiout.dac_nids[i] = 0x24;
1637                                break;
1638                        case AUTO_SEQ_SURROUND:
1639                                spec->multiout.dac_nids[i] = 0x25;
1640                                break;
1641                        case AUTO_SEQ_SIDE:
1642                                spec->multiout.dac_nids[i] = 0x11;
1643                                break;
1644                        }
1645                }
1646        }
1647
1648        return 0;
1649}
1650
1651/* add playback controls from the parsed DAC table */
1652static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
1653                                             const struct auto_pin_cfg *cfg)
1654{
1655        char name[32];
1656        static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1657        hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
1658        hda_nid_t nid, nid_vol = 0;
1659        int i, err;
1660
1661        for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1662                nid = cfg->line_out_pins[i];
1663
1664                if (!nid)
1665                        continue;
1666
1667                nid_vol = nid_vols[i];
1668
1669                if (i == AUTO_SEQ_CENLFE) {
1670                        /* Center/LFE */
1671                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1672                                              "Center Playback Volume",
1673                                              HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1674                                                                  HDA_OUTPUT));
1675                        if (err < 0)
1676                                return err;
1677                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1678                                              "LFE Playback Volume",
1679                                              HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1680                                                                  HDA_OUTPUT));
1681                        if (err < 0)
1682                                return err;
1683                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1684                                              "Center Playback Switch",
1685                                              HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1686                                                                  HDA_OUTPUT));
1687                        if (err < 0)
1688                                return err;
1689                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1690                                              "LFE Playback Switch",
1691                                              HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1692                                                                  HDA_OUTPUT));
1693                        if (err < 0)
1694                                return err;
1695                } else if (i == AUTO_SEQ_FRONT) {
1696                        /* add control to mixer index 0 */
1697                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1698                                              "Master Front Playback Volume",
1699                                              HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1700                                                                  HDA_INPUT));
1701                        if (err < 0)
1702                                return err;
1703                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1704                                              "Master Front Playback Switch",
1705                                              HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1706                                                                  HDA_INPUT));
1707                        if (err < 0)
1708                                return err;
1709
1710                        /* add control to PW3 */
1711                        sprintf(name, "%s Playback Volume", chname[i]);
1712                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1713                                              HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1714                                                                  HDA_OUTPUT));
1715                        if (err < 0)
1716                                return err;
1717                        sprintf(name, "%s Playback Switch", chname[i]);
1718                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1719                                              HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1720                                                                  HDA_OUTPUT));
1721                        if (err < 0)
1722                                return err;
1723                } else {
1724                        sprintf(name, "%s Playback Volume", chname[i]);
1725                        err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1726                                              HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1727                                                                  HDA_OUTPUT));
1728                        if (err < 0)
1729                                return err;
1730                        sprintf(name, "%s Playback Switch", chname[i]);
1731                        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1732                                              HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1733                                                                  HDA_OUTPUT));
1734                        if (err < 0)
1735                                return err;
1736                }
1737        }
1738
1739        return 0;
1740}
1741
1742static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1743{
1744        int err;
1745
1746        if (!pin)
1747                return 0;
1748
1749        spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
1750
1751        err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1752                              "Headphone Playback Volume",
1753                              HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1754        if (err < 0)
1755                return err;
1756        err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1757                              "Headphone Playback Switch",
1758                              HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1759        if (err < 0)
1760                return err;
1761
1762        return 0;
1763}
1764
1765/* create playback/capture controls for input pins */
1766static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
1767                                                const struct auto_pin_cfg *cfg)
1768{
1769        static char *labels[] = {
1770                "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1771        };
1772        struct hda_input_mux *imux = &spec->private_imux;
1773        int i, err, idx = 0;
1774
1775        /* for internal loopback recording select */
1776        imux->items[imux->num_items].label = "Stereo Mixer";
1777        imux->items[imux->num_items].index = idx;
1778        imux->num_items++;
1779
1780        for (i = 0; i < AUTO_PIN_LAST; i++) {
1781                if (!cfg->input_pins[i])
1782                        continue;
1783
1784                switch (cfg->input_pins[i]) {
1785                case 0x1a: /* Mic */
1786                        idx = 2;
1787                        break;
1788
1789                case 0x1b: /* Line In */
1790                        idx = 3;
1791                        break;
1792
1793                case 0x1e: /* Front Mic */
1794                        idx = 4;
1795                        break;
1796
1797                case 0x1f: /* CD */
1798                        idx = 1;
1799                        break;
1800                }
1801                err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1802                                           idx, 0x16);
1803                if (err < 0)
1804                        return err;
1805                imux->items[imux->num_items].label = labels[i];
1806                imux->items[imux->num_items].index = idx;
1807                imux->num_items++;
1808        }
1809        return 0;
1810}
1811
1812static int vt1708B_parse_auto_config(struct hda_codec *codec)
1813{
1814        struct via_spec *spec = codec->spec;
1815        int err;
1816
1817        err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1818        if (err < 0)
1819                return err;
1820        err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
1821        if (err < 0)
1822                return err;
1823        if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1824                return 0; /* can't find valid BIOS pin config */
1825
1826        err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
1827        if (err < 0)
1828                return err;
1829        err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1830        if (err < 0)
1831                return err;
1832        err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
1833        if (err < 0)
1834                return err;
1835
1836        spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1837
1838        if (spec->autocfg.dig_out_pin)
1839                spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
1840        if (spec->autocfg.dig_in_pin)
1841                spec->dig_in_nid = VT1708B_DIGIN_NID;
1842
1843        if (spec->kctl_alloc)
1844                spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1845
1846        spec->input_mux = &spec->private_imux;
1847
1848        return 1;
1849}
1850
1851#ifdef CONFIG_SND_HDA_POWER_SAVE
1852static struct hda_amp_list vt1708B_loopbacks[] = {
1853        { 0x16, HDA_INPUT, 1 },
1854        { 0x16, HDA_INPUT, 2 },
1855        { 0x16, HDA_INPUT, 3 },
1856        { 0x16, HDA_INPUT, 4 },
1857        { } /* end */
1858};
1859#endif
1860
1861static int patch_vt1708B_8ch(struct hda_codec *codec)
1862{
1863        struct via_spec *spec;
1864        int err;
1865
1866        /* create a codec specific record */
1867        spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1868        if (spec == NULL)
1869                return -ENOMEM;
1870
1871        codec->spec = spec;
1872
1873        /* automatic parse from the BIOS config */
1874        err = vt1708B_parse_auto_config(codec);
1875        if (err < 0) {
1876                via_free(codec);
1877                return err;
1878        } else if (!err) {
1879                printk(KERN_INFO "hda_codec: Cannot set up configuration "
1880                       "from BIOS.  Using genenic mode...\n");
1881        }
1882
1883        spec->init_verbs = vt1708B_8ch_volume_init_verbs;
1884
1885        spec->stream_name_analog = "VT1708B Analog";
1886        spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
1887        spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1888
1889        spec->stream_name_digital = "VT1708B Digital";
1890        spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1891        spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1892
1893        if (!spec->adc_nids && spec->input_mux) {
1894                spec->adc_nids = vt1708B_adc_nids;
1895                spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1896                spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1897                spec->num_mixers++;
1898        }
1899
1900        codec->patch_ops = via_patch_ops;
1901
1902        codec->patch_ops.init = via_auto_init;
1903#ifdef CONFIG_SND_HDA_POWER_SAVE
1904        spec->loopback.amplist = vt1708B_loopbacks;
1905#endif
1906
1907        return 0;
1908}
1909
1910static int patch_vt1708B_4ch(struct hda_codec *codec)
1911{
1912        struct via_spec *spec;
1913        int err;
1914
1915        /* create a codec specific record */
1916        spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1917        if (spec == NULL)
1918                return -ENOMEM;
1919
1920        codec->spec = spec;
1921
1922        /* automatic parse from the BIOS config */
1923        err = vt1708B_parse_auto_config(codec);
1924        if (err < 0) {
1925                via_free(codec);
1926                return err;
1927        } else if (!err) {
1928                printk(KERN_INFO "hda_codec: Cannot set up configuration "
1929                       "from BIOS.  Using genenic mode...\n");
1930        }
1931
1932        spec->init_verbs = vt1708B_4ch_volume_init_verbs;
1933
1934        spec->stream_name_analog = "VT1708B Analog";
1935        spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
1936        spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1937
1938        spec->stream_name_digital = "VT1708B Digital";
1939        spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1940        spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1941
1942        if (!spec->adc_nids && spec->input_mux) {
1943                spec->adc_nids = vt1708B_adc_nids;
1944                spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1945                spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1946                spec->num_mixers++;
1947        }
1948
1949        codec->patch_ops = via_patch_ops;
1950
1951        codec->patch_ops.init = via_auto_init;
1952#ifdef CONFIG_SND_HDA_POWER_SAVE
1953        spec->loopback.amplist = vt1708B_loopbacks;
1954#endif
1955
1956        return 0;
1957}
1958
1959/*
1960 * patch entries
1961 */
1962struct hda_codec_preset snd_hda_preset_via[] = {
1963        { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1964        { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1965        { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1966        { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1967        { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
1968          .patch = patch_vt1709_10ch},
1969        { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
1970          .patch = patch_vt1709_10ch},
1971        { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
1972          .patch = patch_vt1709_10ch},
1973        { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
1974          .patch = patch_vt1709_10ch},
1975        { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
1976          .patch = patch_vt1709_6ch},
1977        { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
1978          .patch = patch_vt1709_6ch},
1979        { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
1980          .patch = patch_vt1709_6ch},
1981        { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
1982          .patch = patch_vt1709_6ch},
1983        { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
1984          .patch = patch_vt1708B_8ch},
1985        { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
1986          .patch = patch_vt1708B_8ch},
1987        { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
1988          .patch = patch_vt1708B_8ch},
1989        { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
1990          .patch = patch_vt1708B_8ch},
1991        { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
1992          .patch = patch_vt1708B_4ch},
1993        { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
1994          .patch = patch_vt1708B_4ch},
1995        { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
1996          .patch = patch_vt1708B_4ch},
1997        { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
1998          .patch = patch_vt1708B_4ch},
1999        {} /* terminator */
2000};
2001
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.