linux/sound/pci/hda/patch_via.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Universal Interface for Intel High Definition Audio Codec
   4 *
   5 * HD audio interface patch for VIA VT17xx/VT18xx/VT20xx codec
   6 *
   7 *  (C) 2006-2009 VIA Technology, Inc.
   8 *  (C) 2006-2008 Takashi Iwai <tiwai@suse.de>
   9 */
  10
  11/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
  12/*                                                                           */
  13/* 2006-03-03  Lydia Wang  Create the basic patch to support VT1708 codec    */
  14/* 2006-03-14  Lydia Wang  Modify hard code for some pin widget nid          */
  15/* 2006-08-02  Lydia Wang  Add support to VT1709 codec                       */
  16/* 2006-09-08  Lydia Wang  Fix internal loopback recording source select bug */
  17/* 2007-09-12  Lydia Wang  Add EAPD enable during driver initialization      */
  18/* 2007-09-17  Lydia Wang  Add VT1708B codec support                        */
  19/* 2007-11-14  Lydia Wang  Add VT1708A codec HP and CD pin connect config    */
  20/* 2008-02-03  Lydia Wang  Fix Rear channels and Back channels inverse issue */
  21/* 2008-03-06  Lydia Wang  Add VT1702 codec and VT1708S codec support        */
  22/* 2008-04-09  Lydia Wang  Add mute front speaker when HP plugin             */
  23/* 2008-04-09  Lydia Wang  Add Independent HP feature                        */
  24/* 2008-05-28  Lydia Wang  Add second S/PDIF Out support for VT1702          */
  25/* 2008-09-15  Logan Li    Add VT1708S Mic Boost workaround/backdoor         */
  26/* 2009-02-16  Logan Li    Add support for VT1718S                           */
  27/* 2009-03-13  Logan Li    Add support for VT1716S                           */
  28/* 2009-04-14  Lydai Wang  Add support for VT1828S and VT2020                */
  29/* 2009-07-08  Lydia Wang  Add support for VT2002P                           */
  30/* 2009-07-21  Lydia Wang  Add support for VT1812                            */
  31/* 2009-09-19  Lydia Wang  Add support for VT1818S                           */
  32/*                                                                           */
  33/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  34
  35
  36#include <linux/init.h>
  37#include <linux/delay.h>
  38#include <linux/slab.h>
  39#include <linux/module.h>
  40#include <sound/core.h>
  41#include <sound/asoundef.h>
  42#include <sound/hda_codec.h>
  43#include "hda_local.h"
  44#include "hda_auto_parser.h"
  45#include "hda_jack.h"
  46#include "hda_generic.h"
  47
  48/* Pin Widget NID */
  49#define VT1708_HP_PIN_NID       0x20
  50#define VT1708_CD_PIN_NID       0x24
  51
  52enum VIA_HDA_CODEC {
  53        UNKNOWN = -1,
  54        VT1708,
  55        VT1709_10CH,
  56        VT1709_6CH,
  57        VT1708B_8CH,
  58        VT1708B_4CH,
  59        VT1708S,
  60        VT1708BCE,
  61        VT1702,
  62        VT1718S,
  63        VT1716S,
  64        VT2002P,
  65        VT1812,
  66        VT1802,
  67        VT1705CF,
  68        VT1808,
  69        CODEC_TYPES,
  70};
  71
  72#define VT2002P_COMPATIBLE(spec) \
  73        ((spec)->codec_type == VT2002P ||\
  74         (spec)->codec_type == VT1812 ||\
  75         (spec)->codec_type == VT1802)
  76
  77struct via_spec {
  78        struct hda_gen_spec gen;
  79
  80        /* HP mode source */
  81        unsigned int dmic_enabled;
  82        enum VIA_HDA_CODEC codec_type;
  83
  84        /* analog low-power control */
  85        bool alc_mode;
  86
  87        /* work to check hp jack state */
  88        int hp_work_active;
  89        int vt1708_jack_detect;
  90};
  91
  92static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
  93static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
  94                                  struct hda_codec *codec,
  95                                  struct snd_pcm_substream *substream,
  96                                  int action);
  97
  98static const struct hda_codec_ops via_patch_ops; /* defined below */
  99
 100static struct via_spec *via_new_spec(struct hda_codec *codec)
 101{
 102        struct via_spec *spec;
 103
 104        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 105        if (spec == NULL)
 106                return NULL;
 107
 108        codec->spec = spec;
 109        snd_hda_gen_spec_init(&spec->gen);
 110        spec->codec_type = get_codec_type(codec);
 111        /* VT1708BCE & VT1708S are almost same */
 112        if (spec->codec_type == VT1708BCE)
 113                spec->codec_type = VT1708S;
 114        spec->gen.indep_hp = 1;
 115        spec->gen.keep_eapd_on = 1;
 116        spec->gen.dac_min_mute = 1;
 117        spec->gen.pcm_playback_hook = via_playback_pcm_hook;
 118        spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
 119        codec->power_save_node = 1;
 120        spec->gen.power_down_unused = 1;
 121        codec->patch_ops = via_patch_ops;
 122        return spec;
 123}
 124
 125static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
 126{
 127        u32 vendor_id = codec->core.vendor_id;
 128        u16 ven_id = vendor_id >> 16;
 129        u16 dev_id = vendor_id & 0xffff;
 130        enum VIA_HDA_CODEC codec_type;
 131
 132        /* get codec type */
 133        if (ven_id != 0x1106)
 134                codec_type = UNKNOWN;
 135        else if (dev_id >= 0x1708 && dev_id <= 0x170b)
 136                codec_type = VT1708;
 137        else if (dev_id >= 0xe710 && dev_id <= 0xe713)
 138                codec_type = VT1709_10CH;
 139        else if (dev_id >= 0xe714 && dev_id <= 0xe717)
 140                codec_type = VT1709_6CH;
 141        else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
 142                codec_type = VT1708B_8CH;
 143                if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7)
 144                        codec_type = VT1708BCE;
 145        } else if (dev_id >= 0xe724 && dev_id <= 0xe727)
 146                codec_type = VT1708B_4CH;
 147        else if ((dev_id & 0xfff) == 0x397
 148                 && (dev_id >> 12) < 8)
 149                codec_type = VT1708S;
 150        else if ((dev_id & 0xfff) == 0x398
 151                 && (dev_id >> 12) < 8)
 152                codec_type = VT1702;
 153        else if ((dev_id & 0xfff) == 0x428
 154                 && (dev_id >> 12) < 8)
 155                codec_type = VT1718S;
 156        else if (dev_id == 0x0433 || dev_id == 0xa721)
 157                codec_type = VT1716S;
 158        else if (dev_id == 0x0441 || dev_id == 0x4441)
 159                codec_type = VT1718S;
 160        else if (dev_id == 0x0438 || dev_id == 0x4438)
 161                codec_type = VT2002P;
 162        else if (dev_id == 0x0448)
 163                codec_type = VT1812;
 164        else if (dev_id == 0x0440)
 165                codec_type = VT1708S;
 166        else if ((dev_id & 0xfff) == 0x446)
 167                codec_type = VT1802;
 168        else if (dev_id == 0x4760)
 169                codec_type = VT1705CF;
 170        else if (dev_id == 0x4761 || dev_id == 0x4762)
 171                codec_type = VT1808;
 172        else
 173                codec_type = UNKNOWN;
 174        return codec_type;
 175};
 176
 177static void analog_low_current_mode(struct hda_codec *codec);
 178static bool is_aa_path_mute(struct hda_codec *codec);
 179
 180#define hp_detect_with_aa(codec) \
 181        (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
 182         !is_aa_path_mute(codec))
 183
 184static void vt1708_stop_hp_work(struct hda_codec *codec)
 185{
 186        struct via_spec *spec = codec->spec;
 187        if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
 188                return;
 189        if (spec->hp_work_active) {
 190                snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
 191                codec->jackpoll_interval = 0;
 192                cancel_delayed_work_sync(&codec->jackpoll_work);
 193                spec->hp_work_active = false;
 194        }
 195}
 196
 197static void vt1708_update_hp_work(struct hda_codec *codec)
 198{
 199        struct via_spec *spec = codec->spec;
 200        if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
 201                return;
 202        if (spec->vt1708_jack_detect) {
 203                if (!spec->hp_work_active) {
 204                        codec->jackpoll_interval = msecs_to_jiffies(100);
 205                        snd_hda_codec_write(codec, 0x1, 0, 0xf81, 0);
 206                        schedule_delayed_work(&codec->jackpoll_work, 0);
 207                        spec->hp_work_active = true;
 208                }
 209        } else if (!hp_detect_with_aa(codec))
 210                vt1708_stop_hp_work(codec);
 211}
 212
 213static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
 214                                  struct snd_ctl_elem_info *uinfo)
 215{
 216        return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
 217}
 218
 219static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
 220                                 struct snd_ctl_elem_value *ucontrol)
 221{
 222        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 223        struct via_spec *spec = codec->spec;
 224
 225        ucontrol->value.enumerated.item[0] = spec->gen.power_down_unused;
 226        return 0;
 227}
 228
 229static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
 230                                 struct snd_ctl_elem_value *ucontrol)
 231{
 232        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 233        struct via_spec *spec = codec->spec;
 234        bool val = !!ucontrol->value.enumerated.item[0];
 235
 236        if (val == spec->gen.power_down_unused)
 237                return 0;
 238        /* codec->power_save_node = val; */ /* widget PM seems yet broken */
 239        spec->gen.power_down_unused = val;
 240        analog_low_current_mode(codec);
 241        return 1;
 242}
 243
 244static const struct snd_kcontrol_new via_pin_power_ctl_enum = {
 245        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 246        .name = "Dynamic Power-Control",
 247        .info = via_pin_power_ctl_info,
 248        .get = via_pin_power_ctl_get,
 249        .put = via_pin_power_ctl_put,
 250};
 251
 252#ifdef CONFIG_SND_HDA_INPUT_BEEP
 253/* additional beep mixers; the actual parameters are overwritten at build */
 254static const struct snd_kcontrol_new via_beep_mixer[] = {
 255        HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
 256        HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
 257};
 258
 259static int set_beep_amp(struct via_spec *spec, hda_nid_t nid,
 260                        int idx, int dir)
 261{
 262        struct snd_kcontrol_new *knew;
 263        unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
 264        int i;
 265
 266        spec->gen.beep_nid = nid;
 267        for (i = 0; i < ARRAY_SIZE(via_beep_mixer); i++) {
 268                knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
 269                                            &via_beep_mixer[i]);
 270                if (!knew)
 271                        return -ENOMEM;
 272                knew->private_value = beep_amp;
 273        }
 274        return 0;
 275}
 276
 277static int auto_parse_beep(struct hda_codec *codec)
 278{
 279        struct via_spec *spec = codec->spec;
 280        hda_nid_t nid;
 281
 282        for_each_hda_codec_node(nid, codec)
 283                if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP)
 284                        return set_beep_amp(spec, nid, 0, HDA_OUTPUT);
 285        return 0;
 286}
 287#else
 288#define auto_parse_beep(codec)  0
 289#endif
 290
 291/* check AA path's mute status */
 292static bool is_aa_path_mute(struct hda_codec *codec)
 293{
 294        struct via_spec *spec = codec->spec;
 295        const struct hda_amp_list *p;
 296        int ch, v;
 297
 298        p = spec->gen.loopback.amplist;
 299        if (!p)
 300                return true;
 301        for (; p->nid; p++) {
 302                for (ch = 0; ch < 2; ch++) {
 303                        v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
 304                                                   p->idx);
 305                        if (!(v & HDA_AMP_MUTE) && v > 0)
 306                                return false;
 307                }
 308        }
 309        return true;
 310}
 311
 312/* enter/exit analog low-current mode */
 313static void __analog_low_current_mode(struct hda_codec *codec, bool force)
 314{
 315        struct via_spec *spec = codec->spec;
 316        bool enable;
 317        unsigned int verb, parm;
 318
 319        if (!codec->power_save_node)
 320                enable = false;
 321        else
 322                enable = is_aa_path_mute(codec) && !spec->gen.active_streams;
 323        if (enable == spec->alc_mode && !force)
 324                return;
 325        spec->alc_mode = enable;
 326
 327        /* decide low current mode's verb & parameter */
 328        switch (spec->codec_type) {
 329        case VT1708B_8CH:
 330        case VT1708B_4CH:
 331                verb = 0xf70;
 332                parm = enable ? 0x02 : 0x00; /* 0x02: 2/3x, 0x00: 1x */
 333                break;
 334        case VT1708S:
 335        case VT1718S:
 336        case VT1716S:
 337                verb = 0xf73;
 338                parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */
 339                break;
 340        case VT1702:
 341                verb = 0xf73;
 342                parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */
 343                break;
 344        case VT2002P:
 345        case VT1812:
 346        case VT1802:
 347                verb = 0xf93;
 348                parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
 349                break;
 350        case VT1705CF:
 351        case VT1808:
 352                verb = 0xf82;
 353                parm = enable ? 0x00 : 0xe0;  /* 0x00: 4/40x, 0xe0: 1x */
 354                break;
 355        default:
 356                return;         /* other codecs are not supported */
 357        }
 358        /* send verb */
 359        snd_hda_codec_write(codec, codec->core.afg, 0, verb, parm);
 360}
 361
 362static void analog_low_current_mode(struct hda_codec *codec)
 363{
 364        return __analog_low_current_mode(codec, false);
 365}
 366
 367static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
 368                                  struct hda_codec *codec,
 369                                  struct snd_pcm_substream *substream,
 370                                  int action)
 371{
 372        analog_low_current_mode(codec);
 373        vt1708_update_hp_work(codec);
 374}
 375
 376static void via_free(struct hda_codec *codec)
 377{
 378        vt1708_stop_hp_work(codec);
 379        snd_hda_gen_free(codec);
 380}
 381
 382#ifdef CONFIG_PM
 383static int via_suspend(struct hda_codec *codec)
 384{
 385        struct via_spec *spec = codec->spec;
 386        vt1708_stop_hp_work(codec);
 387
 388        /* Fix pop noise on headphones */
 389        if (spec->codec_type == VT1802)
 390                snd_hda_shutup_pins(codec);
 391
 392        return 0;
 393}
 394
 395static int via_resume(struct hda_codec *codec)
 396{
 397        /* some delay here to make jack detection working (bko#98921) */
 398        msleep(10);
 399        codec->patch_ops.init(codec);
 400        snd_hda_regmap_sync(codec);
 401        return 0;
 402}
 403#endif
 404
 405#ifdef CONFIG_PM
 406static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
 407{
 408        struct via_spec *spec = codec->spec;
 409        analog_low_current_mode(codec);
 410        vt1708_update_hp_work(codec);
 411        return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
 412}
 413#endif
 414
 415/*
 416 */
 417
 418static int via_init(struct hda_codec *codec);
 419
 420static const struct hda_codec_ops via_patch_ops = {
 421        .build_controls = snd_hda_gen_build_controls,
 422        .build_pcms = snd_hda_gen_build_pcms,
 423        .init = via_init,
 424        .free = via_free,
 425        .unsol_event = snd_hda_jack_unsol_event,
 426#ifdef CONFIG_PM
 427        .suspend = via_suspend,
 428        .resume = via_resume,
 429        .check_power_status = via_check_power_status,
 430#endif
 431};
 432
 433
 434static const struct hda_verb vt1708_init_verbs[] = {
 435        /* power down jack detect function */
 436        {0x1, 0xf81, 0x1},
 437        { }
 438};
 439static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
 440{
 441        unsigned int def_conf;
 442        unsigned char seqassoc;
 443
 444        def_conf = snd_hda_codec_get_pincfg(codec, nid);
 445        seqassoc = (unsigned char) get_defcfg_association(def_conf);
 446        seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
 447        if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
 448            && (seqassoc == 0xf0 || seqassoc == 0xff)) {
 449                def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
 450                snd_hda_codec_set_pincfg(codec, nid, def_conf);
 451        }
 452
 453        return;
 454}
 455
 456static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
 457                                     struct snd_ctl_elem_value *ucontrol)
 458{
 459        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 460        struct via_spec *spec = codec->spec;
 461
 462        if (spec->codec_type != VT1708)
 463                return 0;
 464        ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
 465        return 0;
 466}
 467
 468static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
 469                                     struct snd_ctl_elem_value *ucontrol)
 470{
 471        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 472        struct via_spec *spec = codec->spec;
 473        int val;
 474
 475        if (spec->codec_type != VT1708)
 476                return 0;
 477        val = !!ucontrol->value.integer.value[0];
 478        if (spec->vt1708_jack_detect == val)
 479                return 0;
 480        spec->vt1708_jack_detect = val;
 481        vt1708_update_hp_work(codec);
 482        return 1;
 483}
 484
 485static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
 486        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 487        .name = "Jack Detect",
 488        .count = 1,
 489        .info = snd_ctl_boolean_mono_info,
 490        .get = vt1708_jack_detect_get,
 491        .put = vt1708_jack_detect_put,
 492};
 493
 494static const struct badness_table via_main_out_badness = {
 495        .no_primary_dac = 0x10000,
 496        .no_dac = 0x4000,
 497        .shared_primary = 0x10000,
 498        .shared_surr = 0x20,
 499        .shared_clfe = 0x20,
 500        .shared_surr_main = 0x20,
 501};
 502static const struct badness_table via_extra_out_badness = {
 503        .no_primary_dac = 0x4000,
 504        .no_dac = 0x4000,
 505        .shared_primary = 0x12,
 506        .shared_surr = 0x20,
 507        .shared_clfe = 0x20,
 508        .shared_surr_main = 0x10,
 509};
 510
 511static int via_parse_auto_config(struct hda_codec *codec)
 512{
 513        struct via_spec *spec = codec->spec;
 514        int err;
 515
 516        spec->gen.main_out_badness = &via_main_out_badness;
 517        spec->gen.extra_out_badness = &via_extra_out_badness;
 518
 519        err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
 520        if (err < 0)
 521                return err;
 522
 523        err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
 524        if (err < 0)
 525                return err;
 526
 527        err = auto_parse_beep(codec);
 528        if (err < 0)
 529                return err;
 530
 531        if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &via_pin_power_ctl_enum))
 532                return -ENOMEM;
 533
 534        /* disable widget PM at start for compatibility */
 535        codec->power_save_node = 0;
 536        spec->gen.power_down_unused = 0;
 537        return 0;
 538}
 539
 540static int via_init(struct hda_codec *codec)
 541{
 542        /* init power states */
 543        __analog_low_current_mode(codec, true);
 544
 545        snd_hda_gen_init(codec);
 546
 547        vt1708_update_hp_work(codec);
 548
 549        return 0;
 550}
 551
 552static int vt1708_build_controls(struct hda_codec *codec)
 553{
 554        /* In order not to create "Phantom Jack" controls,
 555           temporary enable jackpoll */
 556        int err;
 557        int old_interval = codec->jackpoll_interval;
 558        codec->jackpoll_interval = msecs_to_jiffies(100);
 559        err = snd_hda_gen_build_controls(codec);
 560        codec->jackpoll_interval = old_interval;
 561        return err;
 562}
 563
 564static int vt1708_build_pcms(struct hda_codec *codec)
 565{
 566        struct via_spec *spec = codec->spec;
 567        int i, err;
 568
 569        err = snd_hda_gen_build_pcms(codec);
 570        if (err < 0 || codec->core.vendor_id != 0x11061708)
 571                return err;
 572
 573        /* We got noisy outputs on the right channel on VT1708 when
 574         * 24bit samples are used.  Until any workaround is found,
 575         * disable the 24bit format, so far.
 576         */
 577        for (i = 0; i < ARRAY_SIZE(spec->gen.pcm_rec); i++) {
 578                struct hda_pcm *info = spec->gen.pcm_rec[i];
 579                if (!info)
 580                        continue;
 581                if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
 582                    info->pcm_type != HDA_PCM_TYPE_AUDIO)
 583                        continue;
 584                info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
 585                        SNDRV_PCM_FMTBIT_S16_LE;
 586        }
 587
 588        return 0;
 589}
 590
 591static int patch_vt1708(struct hda_codec *codec)
 592{
 593        struct via_spec *spec;
 594        int err;
 595
 596        /* create a codec specific record */
 597        spec = via_new_spec(codec);
 598        if (spec == NULL)
 599                return -ENOMEM;
 600
 601        /* override some patch_ops */
 602        codec->patch_ops.build_controls = vt1708_build_controls;
 603        codec->patch_ops.build_pcms = vt1708_build_pcms;
 604        spec->gen.mixer_nid = 0x17;
 605
 606        /* set jackpoll_interval while parsing the codec */
 607        codec->jackpoll_interval = msecs_to_jiffies(100);
 608        spec->vt1708_jack_detect = 1;
 609
 610        /* don't support the input jack switching due to lack of unsol event */
 611        /* (it may work with polling, though, but it needs testing) */
 612        spec->gen.suppress_auto_mic = 1;
 613        /* Some machines show the broken speaker mute */
 614        spec->gen.auto_mute_via_amp = 1;
 615
 616        /* Add HP and CD pin config connect bit re-config action */
 617        vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
 618        vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
 619
 620        err = snd_hda_add_verbs(codec, vt1708_init_verbs);
 621        if (err < 0)
 622                goto error;
 623
 624        /* automatic parse from the BIOS config */
 625        err = via_parse_auto_config(codec);
 626        if (err < 0)
 627                goto error;
 628
 629        /* add jack detect on/off control */
 630        if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1708_jack_detect_ctl)) {
 631                err = -ENOMEM;
 632                goto error;
 633        }
 634
 635        /* clear jackpoll_interval again; it's set dynamically */
 636        codec->jackpoll_interval = 0;
 637
 638        return 0;
 639
 640 error:
 641        via_free(codec);
 642        return err;
 643}
 644
 645static int patch_vt1709(struct hda_codec *codec)
 646{
 647        struct via_spec *spec;
 648        int err;
 649
 650        /* create a codec specific record */
 651        spec = via_new_spec(codec);
 652        if (spec == NULL)
 653                return -ENOMEM;
 654
 655        spec->gen.mixer_nid = 0x18;
 656
 657        err = via_parse_auto_config(codec);
 658        if (err < 0)
 659                goto error;
 660
 661        return 0;
 662
 663 error:
 664        via_free(codec);
 665        return err;
 666}
 667
 668static int patch_vt1708S(struct hda_codec *codec);
 669static int patch_vt1708B(struct hda_codec *codec)
 670{
 671        struct via_spec *spec;
 672        int err;
 673
 674        if (get_codec_type(codec) == VT1708BCE)
 675                return patch_vt1708S(codec);
 676
 677        /* create a codec specific record */
 678        spec = via_new_spec(codec);
 679        if (spec == NULL)
 680                return -ENOMEM;
 681
 682        spec->gen.mixer_nid = 0x16;
 683
 684        /* automatic parse from the BIOS config */
 685        err = via_parse_auto_config(codec);
 686        if (err < 0)
 687                goto error;
 688
 689        return 0;
 690
 691 error:
 692        via_free(codec);
 693        return err;
 694}
 695
 696/* Patch for VT1708S */
 697static const struct hda_verb vt1708S_init_verbs[] = {
 698        /* Enable Mic Boost Volume backdoor */
 699        {0x1, 0xf98, 0x1},
 700        /* don't bybass mixer */
 701        {0x1, 0xf88, 0xc0},
 702        { }
 703};
 704
 705static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
 706                               int offset, int num_steps, int step_size)
 707{
 708        snd_hda_override_wcaps(codec, pin,
 709                               get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
 710        snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
 711                                  (offset << AC_AMPCAP_OFFSET_SHIFT) |
 712                                  (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
 713                                  (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
 714                                  (0 << AC_AMPCAP_MUTE_SHIFT));
 715}
 716
 717static int patch_vt1708S(struct hda_codec *codec)
 718{
 719        struct via_spec *spec;
 720        int err;
 721
 722        /* create a codec specific record */
 723        spec = via_new_spec(codec);
 724        if (spec == NULL)
 725                return -ENOMEM;
 726
 727        spec->gen.mixer_nid = 0x16;
 728        override_mic_boost(codec, 0x1a, 0, 3, 40);
 729        override_mic_boost(codec, 0x1e, 0, 3, 40);
 730
 731        /* correct names for VT1708BCE */
 732        if (get_codec_type(codec) == VT1708BCE)
 733                snd_hda_codec_set_name(codec, "VT1708BCE");
 734        /* correct names for VT1705 */
 735        if (codec->core.vendor_id == 0x11064397)
 736                snd_hda_codec_set_name(codec, "VT1705");
 737
 738        err = snd_hda_add_verbs(codec, vt1708S_init_verbs);
 739        if (err < 0)
 740                goto error;
 741
 742        /* automatic parse from the BIOS config */
 743        err = via_parse_auto_config(codec);
 744        if (err < 0)
 745                goto error;
 746
 747        return 0;
 748
 749 error:
 750        via_free(codec);
 751        return err;
 752}
 753
 754/* Patch for VT1702 */
 755
 756static const struct hda_verb vt1702_init_verbs[] = {
 757        /* mixer enable */
 758        {0x1, 0xF88, 0x3},
 759        /* GPIO 0~2 */
 760        {0x1, 0xF82, 0x3F},
 761        { }
 762};
 763
 764static int patch_vt1702(struct hda_codec *codec)
 765{
 766        struct via_spec *spec;
 767        int err;
 768
 769        /* create a codec specific record */
 770        spec = via_new_spec(codec);
 771        if (spec == NULL)
 772                return -ENOMEM;
 773
 774        spec->gen.mixer_nid = 0x1a;
 775
 776        /* limit AA path volume to 0 dB */
 777        snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
 778                                  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
 779                                  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
 780                                  (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
 781                                  (1 << AC_AMPCAP_MUTE_SHIFT));
 782
 783        err = snd_hda_add_verbs(codec, vt1702_init_verbs);
 784        if (err < 0)
 785                goto error;
 786
 787        /* automatic parse from the BIOS config */
 788        err = via_parse_auto_config(codec);
 789        if (err < 0)
 790                goto error;
 791
 792        return 0;
 793
 794 error:
 795        via_free(codec);
 796        return err;
 797}
 798
 799/* Patch for VT1718S */
 800
 801static const struct hda_verb vt1718S_init_verbs[] = {
 802        /* Enable MW0 adjust Gain 5 */
 803        {0x1, 0xfb2, 0x10},
 804        /* Enable Boost Volume backdoor */
 805        {0x1, 0xf88, 0x8},
 806
 807        { }
 808};
 809
 810/* Add a connection to the primary DAC from AA-mixer for some codecs
 811 * This isn't listed from the raw info, but the chip has a secret connection.
 812 */
 813static int add_secret_dac_path(struct hda_codec *codec)
 814{
 815        struct via_spec *spec = codec->spec;
 816        int i, nums;
 817        hda_nid_t conn[8];
 818        hda_nid_t nid;
 819
 820        if (!spec->gen.mixer_nid)
 821                return 0;
 822        nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
 823                                       ARRAY_SIZE(conn) - 1);
 824        for (i = 0; i < nums; i++) {
 825                if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
 826                        return 0;
 827        }
 828
 829        /* find the primary DAC and add to the connection list */
 830        for_each_hda_codec_node(nid, codec) {
 831                unsigned int caps = get_wcaps(codec, nid);
 832                if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
 833                    !(caps & AC_WCAP_DIGITAL)) {
 834                        conn[nums++] = nid;
 835                        return snd_hda_override_conn_list(codec,
 836                                                          spec->gen.mixer_nid,
 837                                                          nums, conn);
 838                }
 839        }
 840        return 0;
 841}
 842
 843
 844static int patch_vt1718S(struct hda_codec *codec)
 845{
 846        struct via_spec *spec;
 847        int err;
 848
 849        /* create a codec specific record */
 850        spec = via_new_spec(codec);
 851        if (spec == NULL)
 852                return -ENOMEM;
 853
 854        spec->gen.mixer_nid = 0x21;
 855        override_mic_boost(codec, 0x2b, 0, 3, 40);
 856        override_mic_boost(codec, 0x29, 0, 3, 40);
 857        add_secret_dac_path(codec);
 858
 859        err = snd_hda_add_verbs(codec, vt1718S_init_verbs);
 860        if (err < 0)
 861                goto error;
 862
 863        /* automatic parse from the BIOS config */
 864        err = via_parse_auto_config(codec);
 865        if (err < 0)
 866                goto error;
 867
 868        return 0;
 869
 870 error:
 871        via_free(codec);
 872        return err;
 873}
 874
 875/* Patch for VT1716S */
 876
 877static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
 878                            struct snd_ctl_elem_info *uinfo)
 879{
 880        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 881        uinfo->count = 1;
 882        uinfo->value.integer.min = 0;
 883        uinfo->value.integer.max = 1;
 884        return 0;
 885}
 886
 887static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
 888                           struct snd_ctl_elem_value *ucontrol)
 889{
 890        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 891        int index = 0;
 892
 893        index = snd_hda_codec_read(codec, 0x26, 0,
 894                                               AC_VERB_GET_CONNECT_SEL, 0);
 895        if (index != -1)
 896                *ucontrol->value.integer.value = index;
 897
 898        return 0;
 899}
 900
 901static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
 902                           struct snd_ctl_elem_value *ucontrol)
 903{
 904        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 905        struct via_spec *spec = codec->spec;
 906        int index = *ucontrol->value.integer.value;
 907
 908        snd_hda_codec_write(codec, 0x26, 0,
 909                                               AC_VERB_SET_CONNECT_SEL, index);
 910        spec->dmic_enabled = index;
 911        return 1;
 912}
 913
 914static const struct snd_kcontrol_new vt1716s_dmic_mixer_vol =
 915        HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT);
 916static const struct snd_kcontrol_new vt1716s_dmic_mixer_sw = {
 917         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 918         .name = "Digital Mic Capture Switch",
 919         .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
 920         .count = 1,
 921         .info = vt1716s_dmic_info,
 922         .get = vt1716s_dmic_get,
 923         .put = vt1716s_dmic_put,
 924};
 925
 926
 927/* mono-out mixer elements */
 928static const struct snd_kcontrol_new vt1716S_mono_out_mixer =
 929        HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT);
 930
 931static const struct hda_verb vt1716S_init_verbs[] = {
 932        /* Enable Boost Volume backdoor */
 933        {0x1, 0xf8a, 0x80},
 934        /* don't bybass mixer */
 935        {0x1, 0xf88, 0xc0},
 936        /* Enable mono output */
 937        {0x1, 0xf90, 0x08},
 938        { }
 939};
 940
 941static int patch_vt1716S(struct hda_codec *codec)
 942{
 943        struct via_spec *spec;
 944        int err;
 945
 946        /* create a codec specific record */
 947        spec = via_new_spec(codec);
 948        if (spec == NULL)
 949                return -ENOMEM;
 950
 951        spec->gen.mixer_nid = 0x16;
 952        override_mic_boost(codec, 0x1a, 0, 3, 40);
 953        override_mic_boost(codec, 0x1e, 0, 3, 40);
 954
 955        err = snd_hda_add_verbs(codec, vt1716S_init_verbs);
 956        if (err < 0)
 957                goto error;
 958
 959        /* automatic parse from the BIOS config */
 960        err = via_parse_auto_config(codec);
 961        if (err < 0)
 962                goto error;
 963
 964        if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) ||
 965            !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) ||
 966            !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) {
 967                err = -ENOMEM;
 968                goto error;
 969        }
 970
 971        return 0;
 972
 973 error:
 974        via_free(codec);
 975        return err;
 976}
 977
 978/* for vt2002P */
 979
 980static const struct hda_verb vt2002P_init_verbs[] = {
 981        /* Class-D speaker related verbs */
 982        {0x1, 0xfe0, 0x4},
 983        {0x1, 0xfe9, 0x80},
 984        {0x1, 0xfe2, 0x22},
 985        /* Enable Boost Volume backdoor */
 986        {0x1, 0xfb9, 0x24},
 987        /* Enable AOW0 to MW9 */
 988        {0x1, 0xfb8, 0x88},
 989        { }
 990};
 991
 992static const struct hda_verb vt1802_init_verbs[] = {
 993        /* Enable Boost Volume backdoor */
 994        {0x1, 0xfb9, 0x24},
 995        /* Enable AOW0 to MW9 */
 996        {0x1, 0xfb8, 0x88},
 997        { }
 998};
 999
1000/*
1001 * pin fix-up
1002 */
1003enum {
1004        VIA_FIXUP_INTMIC_BOOST,
1005        VIA_FIXUP_ASUS_G75,
1006        VIA_FIXUP_POWER_SAVE,
1007};
1008
1009static void via_fixup_intmic_boost(struct hda_codec *codec,
1010                                  const struct hda_fixup *fix, int action)
1011{
1012        if (action == HDA_FIXUP_ACT_PRE_PROBE)
1013                override_mic_boost(codec, 0x30, 0, 2, 40);
1014}
1015
1016static void via_fixup_power_save(struct hda_codec *codec,
1017                                 const struct hda_fixup *fix, int action)
1018{
1019        if (action == HDA_FIXUP_ACT_PRE_PROBE)
1020                codec->power_save_node = 0;
1021}
1022
1023static const struct hda_fixup via_fixups[] = {
1024        [VIA_FIXUP_INTMIC_BOOST] = {
1025                .type = HDA_FIXUP_FUNC,
1026                .v.func = via_fixup_intmic_boost,
1027        },
1028        [VIA_FIXUP_ASUS_G75] = {
1029                .type = HDA_FIXUP_PINS,
1030                .v.pins = (const struct hda_pintbl[]) {
1031                        /* set 0x24 and 0x33 as speakers */
1032                        { 0x24, 0x991301f0 },
1033                        { 0x33, 0x991301f1 }, /* subwoofer */
1034                        { }
1035                }
1036        },
1037        [VIA_FIXUP_POWER_SAVE] = {
1038                .type = HDA_FIXUP_FUNC,
1039                .v.func = via_fixup_power_save,
1040        },
1041};
1042
1043static const struct snd_pci_quirk vt2002p_fixups[] = {
1044        SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
1045        SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
1046        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE),
1047        {}
1048};
1049
1050/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
1051 * Replace this with mixer NID 0x1c
1052 */
1053static void fix_vt1802_connections(struct hda_codec *codec)
1054{
1055        static const hda_nid_t conn_24[] = { 0x14, 0x1c };
1056        static const hda_nid_t conn_33[] = { 0x1c };
1057
1058        snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
1059        snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
1060}
1061
1062/* patch for vt2002P */
1063static int patch_vt2002P(struct hda_codec *codec)
1064{
1065        struct via_spec *spec;
1066        int err;
1067
1068        /* create a codec specific record */
1069        spec = via_new_spec(codec);
1070        if (spec == NULL)
1071                return -ENOMEM;
1072
1073        spec->gen.mixer_nid = 0x21;
1074        override_mic_boost(codec, 0x2b, 0, 3, 40);
1075        override_mic_boost(codec, 0x29, 0, 3, 40);
1076        if (spec->codec_type == VT1802)
1077                fix_vt1802_connections(codec);
1078        add_secret_dac_path(codec);
1079
1080        snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
1081        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1082
1083        if (spec->codec_type == VT1802)
1084                err = snd_hda_add_verbs(codec, vt1802_init_verbs);
1085        else
1086                err = snd_hda_add_verbs(codec, vt2002P_init_verbs);
1087        if (err < 0)
1088                goto error;
1089
1090        /* automatic parse from the BIOS config */
1091        err = via_parse_auto_config(codec);
1092        if (err < 0)
1093                goto error;
1094
1095        return 0;
1096
1097 error:
1098        via_free(codec);
1099        return err;
1100}
1101
1102/* for vt1812 */
1103
1104static const struct hda_verb vt1812_init_verbs[] = {
1105        /* Enable Boost Volume backdoor */
1106        {0x1, 0xfb9, 0x24},
1107        /* Enable AOW0 to MW9 */
1108        {0x1, 0xfb8, 0xa8},
1109        { }
1110};
1111
1112/* patch for vt1812 */
1113static int patch_vt1812(struct hda_codec *codec)
1114{
1115        struct via_spec *spec;
1116        int err;
1117
1118        /* create a codec specific record */
1119        spec = via_new_spec(codec);
1120        if (spec == NULL)
1121                return -ENOMEM;
1122
1123        spec->gen.mixer_nid = 0x21;
1124        override_mic_boost(codec, 0x2b, 0, 3, 40);
1125        override_mic_boost(codec, 0x29, 0, 3, 40);
1126        add_secret_dac_path(codec);
1127
1128        err = snd_hda_add_verbs(codec, vt1812_init_verbs);
1129        if (err < 0)
1130                goto error;
1131
1132        /* automatic parse from the BIOS config */
1133        err = via_parse_auto_config(codec);
1134        if (err < 0)
1135                goto error;
1136
1137        return 0;
1138
1139 error:
1140        via_free(codec);
1141        return err;
1142}
1143
1144/* patch for vt3476 */
1145
1146static const struct hda_verb vt3476_init_verbs[] = {
1147        /* Enable DMic 8/16/32K */
1148        {0x1, 0xF7B, 0x30},
1149        /* Enable Boost Volume backdoor */
1150        {0x1, 0xFB9, 0x20},
1151        /* Enable AOW-MW9 path */
1152        {0x1, 0xFB8, 0x10},
1153        { }
1154};
1155
1156static int patch_vt3476(struct hda_codec *codec)
1157{
1158        struct via_spec *spec;
1159        int err;
1160
1161        /* create a codec specific record */
1162        spec = via_new_spec(codec);
1163        if (spec == NULL)
1164                return -ENOMEM;
1165
1166        spec->gen.mixer_nid = 0x3f;
1167        add_secret_dac_path(codec);
1168
1169        err = snd_hda_add_verbs(codec, vt3476_init_verbs);
1170        if (err < 0)
1171                goto error;
1172
1173        /* automatic parse from the BIOS config */
1174        err = via_parse_auto_config(codec);
1175        if (err < 0)
1176                goto error;
1177
1178        return 0;
1179
1180 error:
1181        via_free(codec);
1182        return err;
1183}
1184
1185/*
1186 * patch entries
1187 */
1188static const struct hda_device_id snd_hda_id_via[] = {
1189        HDA_CODEC_ENTRY(0x11061708, "VT1708", patch_vt1708),
1190        HDA_CODEC_ENTRY(0x11061709, "VT1708", patch_vt1708),
1191        HDA_CODEC_ENTRY(0x1106170a, "VT1708", patch_vt1708),
1192        HDA_CODEC_ENTRY(0x1106170b, "VT1708", patch_vt1708),
1193        HDA_CODEC_ENTRY(0x1106e710, "VT1709 10-Ch", patch_vt1709),
1194        HDA_CODEC_ENTRY(0x1106e711, "VT1709 10-Ch", patch_vt1709),
1195        HDA_CODEC_ENTRY(0x1106e712, "VT1709 10-Ch", patch_vt1709),
1196        HDA_CODEC_ENTRY(0x1106e713, "VT1709 10-Ch", patch_vt1709),
1197        HDA_CODEC_ENTRY(0x1106e714, "VT1709 6-Ch", patch_vt1709),
1198        HDA_CODEC_ENTRY(0x1106e715, "VT1709 6-Ch", patch_vt1709),
1199        HDA_CODEC_ENTRY(0x1106e716, "VT1709 6-Ch", patch_vt1709),
1200        HDA_CODEC_ENTRY(0x1106e717, "VT1709 6-Ch", patch_vt1709),
1201        HDA_CODEC_ENTRY(0x1106e720, "VT1708B 8-Ch", patch_vt1708B),
1202        HDA_CODEC_ENTRY(0x1106e721, "VT1708B 8-Ch", patch_vt1708B),
1203        HDA_CODEC_ENTRY(0x1106e722, "VT1708B 8-Ch", patch_vt1708B),
1204        HDA_CODEC_ENTRY(0x1106e723, "VT1708B 8-Ch", patch_vt1708B),
1205        HDA_CODEC_ENTRY(0x1106e724, "VT1708B 4-Ch", patch_vt1708B),
1206        HDA_CODEC_ENTRY(0x1106e725, "VT1708B 4-Ch", patch_vt1708B),
1207        HDA_CODEC_ENTRY(0x1106e726, "VT1708B 4-Ch", patch_vt1708B),
1208        HDA_CODEC_ENTRY(0x1106e727, "VT1708B 4-Ch", patch_vt1708B),
1209        HDA_CODEC_ENTRY(0x11060397, "VT1708S", patch_vt1708S),
1210        HDA_CODEC_ENTRY(0x11061397, "VT1708S", patch_vt1708S),
1211        HDA_CODEC_ENTRY(0x11062397, "VT1708S", patch_vt1708S),
1212        HDA_CODEC_ENTRY(0x11063397, "VT1708S", patch_vt1708S),
1213        HDA_CODEC_ENTRY(0x11064397, "VT1705", patch_vt1708S),
1214        HDA_CODEC_ENTRY(0x11065397, "VT1708S", patch_vt1708S),
1215        HDA_CODEC_ENTRY(0x11066397, "VT1708S", patch_vt1708S),
1216        HDA_CODEC_ENTRY(0x11067397, "VT1708S", patch_vt1708S),
1217        HDA_CODEC_ENTRY(0x11060398, "VT1702", patch_vt1702),
1218        HDA_CODEC_ENTRY(0x11061398, "VT1702", patch_vt1702),
1219        HDA_CODEC_ENTRY(0x11062398, "VT1702", patch_vt1702),
1220        HDA_CODEC_ENTRY(0x11063398, "VT1702", patch_vt1702),
1221        HDA_CODEC_ENTRY(0x11064398, "VT1702", patch_vt1702),
1222        HDA_CODEC_ENTRY(0x11065398, "VT1702", patch_vt1702),
1223        HDA_CODEC_ENTRY(0x11066398, "VT1702", patch_vt1702),
1224        HDA_CODEC_ENTRY(0x11067398, "VT1702", patch_vt1702),
1225        HDA_CODEC_ENTRY(0x11060428, "VT1718S", patch_vt1718S),
1226        HDA_CODEC_ENTRY(0x11064428, "VT1718S", patch_vt1718S),
1227        HDA_CODEC_ENTRY(0x11060441, "VT2020", patch_vt1718S),
1228        HDA_CODEC_ENTRY(0x11064441, "VT1828S", patch_vt1718S),
1229        HDA_CODEC_ENTRY(0x11060433, "VT1716S", patch_vt1716S),
1230        HDA_CODEC_ENTRY(0x1106a721, "VT1716S", patch_vt1716S),
1231        HDA_CODEC_ENTRY(0x11060438, "VT2002P", patch_vt2002P),
1232        HDA_CODEC_ENTRY(0x11064438, "VT2002P", patch_vt2002P),
1233        HDA_CODEC_ENTRY(0x11060448, "VT1812", patch_vt1812),
1234        HDA_CODEC_ENTRY(0x11060440, "VT1818S", patch_vt1708S),
1235        HDA_CODEC_ENTRY(0x11060446, "VT1802", patch_vt2002P),
1236        HDA_CODEC_ENTRY(0x11068446, "VT1802", patch_vt2002P),
1237        HDA_CODEC_ENTRY(0x11064760, "VT1705CF", patch_vt3476),
1238        HDA_CODEC_ENTRY(0x11064761, "VT1708SCE", patch_vt3476),
1239        HDA_CODEC_ENTRY(0x11064762, "VT1808", patch_vt3476),
1240        {} /* terminator */
1241};
1242MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_via);
1243
1244static struct hda_codec_driver via_driver = {
1245        .id = snd_hda_id_via,
1246};
1247
1248MODULE_LICENSE("GPL");
1249MODULE_DESCRIPTION("VIA HD-audio codec");
1250
1251module_hda_codec_driver(via_driver);
1252