linux/sound/pci/hda/patch_cirrus.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * HD audio interface patch for Cirrus Logic CS420x chip
   4 *
   5 * Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
   6 */
   7
   8#include <linux/init.h>
   9#include <linux/slab.h>
  10#include <linux/module.h>
  11#include <sound/core.h>
  12#include <sound/tlv.h>
  13#include <sound/hda_codec.h>
  14#include "hda_local.h"
  15#include "hda_auto_parser.h"
  16#include "hda_jack.h"
  17#include "hda_generic.h"
  18
  19/*
  20 */
  21
  22struct cs_spec {
  23        struct hda_gen_spec gen;
  24
  25        unsigned int gpio_mask;
  26        unsigned int gpio_dir;
  27        unsigned int gpio_data;
  28        unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */
  29        unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */
  30
  31        /* CS421x */
  32        unsigned int spdif_detect:1;
  33        unsigned int spdif_present:1;
  34        unsigned int sense_b:1;
  35        hda_nid_t vendor_nid;
  36
  37        /* for MBP SPDIF control */
  38        int (*spdif_sw_put)(struct snd_kcontrol *kcontrol,
  39                            struct snd_ctl_elem_value *ucontrol);
  40};
  41
  42/* available models with CS420x */
  43enum {
  44        CS420X_MBP53,
  45        CS420X_MBP55,
  46        CS420X_IMAC27,
  47        CS420X_GPIO_13,
  48        CS420X_GPIO_23,
  49        CS420X_MBP101,
  50        CS420X_MBP81,
  51        CS420X_MBA42,
  52        CS420X_AUTO,
  53        /* aliases */
  54        CS420X_IMAC27_122 = CS420X_GPIO_23,
  55        CS420X_APPLE = CS420X_GPIO_13,
  56};
  57
  58/* CS421x boards */
  59enum {
  60        CS421X_CDB4210,
  61        CS421X_SENSE_B,
  62        CS421X_STUMPY,
  63};
  64
  65/* Vendor-specific processing widget */
  66#define CS420X_VENDOR_NID       0x11
  67#define CS_DIG_OUT1_PIN_NID     0x10
  68#define CS_DIG_OUT2_PIN_NID     0x15
  69#define CS_DMIC1_PIN_NID        0x0e
  70#define CS_DMIC2_PIN_NID        0x12
  71
  72/* coef indices */
  73#define IDX_SPDIF_STAT          0x0000
  74#define IDX_SPDIF_CTL           0x0001
  75#define IDX_ADC_CFG             0x0002
  76/* SZC bitmask, 4 modes below:
  77 * 0 = immediate,
  78 * 1 = digital immediate, analog zero-cross
  79 * 2 = digtail & analog soft-ramp
  80 * 3 = digital soft-ramp, analog zero-cross
  81 */
  82#define   CS_COEF_ADC_SZC_MASK          (3 << 0)
  83#define   CS_COEF_ADC_MIC_SZC_MODE      (3 << 0) /* SZC setup for mic */
  84#define   CS_COEF_ADC_LI_SZC_MODE       (3 << 0) /* SZC setup for line-in */
  85/* PGA mode: 0 = differential, 1 = signle-ended */
  86#define   CS_COEF_ADC_MIC_PGA_MODE      (1 << 5) /* PGA setup for mic */
  87#define   CS_COEF_ADC_LI_PGA_MODE       (1 << 6) /* PGA setup for line-in */
  88#define IDX_DAC_CFG             0x0003
  89/* SZC bitmask, 4 modes below:
  90 * 0 = Immediate
  91 * 1 = zero-cross
  92 * 2 = soft-ramp
  93 * 3 = soft-ramp on zero-cross
  94 */
  95#define   CS_COEF_DAC_HP_SZC_MODE       (3 << 0) /* nid 0x02 */
  96#define   CS_COEF_DAC_LO_SZC_MODE       (3 << 2) /* nid 0x03 */
  97#define   CS_COEF_DAC_SPK_SZC_MODE      (3 << 4) /* nid 0x04 */
  98
  99#define IDX_BEEP_CFG            0x0004
 100/* 0x0008 - test reg key */
 101/* 0x0009 - 0x0014 -> 12 test regs */
 102/* 0x0015 - visibility reg */
 103
 104/* Cirrus Logic CS4208 */
 105#define CS4208_VENDOR_NID       0x24
 106
 107/*
 108 * Cirrus Logic CS4210
 109 *
 110 * 1 DAC => HP(sense) / Speakers,
 111 * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
 112 * 1 SPDIF OUT => SPDIF Trasmitter(sense)
 113*/
 114#define CS4210_DAC_NID          0x02
 115#define CS4210_ADC_NID          0x03
 116#define CS4210_VENDOR_NID       0x0B
 117#define CS421X_DMIC_PIN_NID     0x09 /* Port E */
 118#define CS421X_SPDIF_PIN_NID    0x0A /* Port H */
 119
 120#define CS421X_IDX_DEV_CFG      0x01
 121#define CS421X_IDX_ADC_CFG      0x02
 122#define CS421X_IDX_DAC_CFG      0x03
 123#define CS421X_IDX_SPK_CTL      0x04
 124
 125/* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */
 126#define CS4213_VENDOR_NID       0x09
 127
 128
 129static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
 130{
 131        struct cs_spec *spec = codec->spec;
 132        snd_hda_codec_write(codec, spec->vendor_nid, 0,
 133                            AC_VERB_SET_COEF_INDEX, idx);
 134        return snd_hda_codec_read(codec, spec->vendor_nid, 0,
 135                                  AC_VERB_GET_PROC_COEF, 0);
 136}
 137
 138static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
 139                                      unsigned int coef)
 140{
 141        struct cs_spec *spec = codec->spec;
 142        snd_hda_codec_write(codec, spec->vendor_nid, 0,
 143                            AC_VERB_SET_COEF_INDEX, idx);
 144        snd_hda_codec_write(codec, spec->vendor_nid, 0,
 145                            AC_VERB_SET_PROC_COEF, coef);
 146}
 147
 148/*
 149 * auto-mute and auto-mic switching
 150 * CS421x auto-output redirecting
 151 * HP/SPK/SPDIF
 152 */
 153
 154static void cs_automute(struct hda_codec *codec)
 155{
 156        struct cs_spec *spec = codec->spec;
 157
 158        /* mute HPs if spdif jack (SENSE_B) is present */
 159        spec->gen.master_mute = !!(spec->spdif_present && spec->sense_b);
 160
 161        snd_hda_gen_update_outputs(codec);
 162
 163        if (spec->gpio_eapd_hp || spec->gpio_eapd_speaker) {
 164                if (spec->gen.automute_speaker)
 165                        spec->gpio_data = spec->gen.hp_jack_present ?
 166                                spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
 167                else
 168                        spec->gpio_data =
 169                                spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
 170                snd_hda_codec_write(codec, 0x01, 0,
 171                                    AC_VERB_SET_GPIO_DATA, spec->gpio_data);
 172        }
 173}
 174
 175static bool is_active_pin(struct hda_codec *codec, hda_nid_t nid)
 176{
 177        unsigned int val;
 178        val = snd_hda_codec_get_pincfg(codec, nid);
 179        return (get_defcfg_connect(val) != AC_JACK_PORT_NONE);
 180}
 181
 182static void init_input_coef(struct hda_codec *codec)
 183{
 184        struct cs_spec *spec = codec->spec;
 185        unsigned int coef;
 186
 187        /* CS420x has multiple ADC, CS421x has single ADC */
 188        if (spec->vendor_nid == CS420X_VENDOR_NID) {
 189                coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);
 190                if (is_active_pin(codec, CS_DMIC2_PIN_NID))
 191                        coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */
 192                if (is_active_pin(codec, CS_DMIC1_PIN_NID))
 193                        coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off
 194                                         * No effect if SPDIF_OUT2 is
 195                                         * selected in IDX_SPDIF_CTL.
 196                                        */
 197
 198                cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef);
 199        }
 200}
 201
 202static const struct hda_verb cs_coef_init_verbs[] = {
 203        {0x11, AC_VERB_SET_PROC_STATE, 1},
 204        {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
 205        {0x11, AC_VERB_SET_PROC_COEF,
 206         (0x002a /* DAC1/2/3 SZCMode Soft Ramp */
 207          | 0x0040 /* Mute DACs on FIFO error */
 208          | 0x1000 /* Enable DACs High Pass Filter */
 209          | 0x0400 /* Disable Coefficient Auto increment */
 210          )},
 211        /* ADC1/2 - Digital and Analog Soft Ramp */
 212        {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG},
 213        {0x11, AC_VERB_SET_PROC_COEF, 0x000a},
 214        /* Beep */
 215        {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},
 216        {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
 217
 218        {} /* terminator */
 219};
 220
 221static const struct hda_verb cs4208_coef_init_verbs[] = {
 222        {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */
 223        {0x24, AC_VERB_SET_PROC_STATE, 0x01},  /* VPW: processing on */
 224        {0x24, AC_VERB_SET_COEF_INDEX, 0x0033},
 225        {0x24, AC_VERB_SET_PROC_COEF, 0x0001}, /* A1 ICS */
 226        {0x24, AC_VERB_SET_COEF_INDEX, 0x0034},
 227        {0x24, AC_VERB_SET_PROC_COEF, 0x1C01}, /* A1 Enable, A Thresh = 300mV */
 228        {} /* terminator */
 229};
 230
 231/* Errata: CS4207 rev C0/C1/C2 Silicon
 232 *
 233 * http://www.cirrus.com/en/pubs/errata/ER880C3.pdf
 234 *
 235 * 6. At high temperature (TA > +85°C), the digital supply current (IVD)
 236 * may be excessive (up to an additional 200 μA), which is most easily
 237 * observed while the part is being held in reset (RESET# active low).
 238 *
 239 * Root Cause: At initial powerup of the device, the logic that drives
 240 * the clock and write enable to the S/PDIF SRC RAMs is not properly
 241 * initialized.
 242 * Certain random patterns will cause a steady leakage current in those
 243 * RAM cells. The issue will resolve once the SRCs are used (turned on).
 244 *
 245 * Workaround: The following verb sequence briefly turns on the S/PDIF SRC
 246 * blocks, which will alleviate the issue.
 247 */
 248
 249static const struct hda_verb cs_errata_init_verbs[] = {
 250        {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */
 251        {0x11, AC_VERB_SET_PROC_STATE, 0x01},  /* VPW: processing on */
 252
 253        {0x11, AC_VERB_SET_COEF_INDEX, 0x0008},
 254        {0x11, AC_VERB_SET_PROC_COEF, 0x9999},
 255        {0x11, AC_VERB_SET_COEF_INDEX, 0x0017},
 256        {0x11, AC_VERB_SET_PROC_COEF, 0xa412},
 257        {0x11, AC_VERB_SET_COEF_INDEX, 0x0001},
 258        {0x11, AC_VERB_SET_PROC_COEF, 0x0009},
 259
 260        {0x07, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Rx: D0 */
 261        {0x08, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Tx: D0 */
 262
 263        {0x11, AC_VERB_SET_COEF_INDEX, 0x0017},
 264        {0x11, AC_VERB_SET_PROC_COEF, 0x2412},
 265        {0x11, AC_VERB_SET_COEF_INDEX, 0x0008},
 266        {0x11, AC_VERB_SET_PROC_COEF, 0x0000},
 267        {0x11, AC_VERB_SET_COEF_INDEX, 0x0001},
 268        {0x11, AC_VERB_SET_PROC_COEF, 0x0008},
 269        {0x11, AC_VERB_SET_PROC_STATE, 0x00},
 270
 271#if 0 /* Don't to set to D3 as we are in power-up sequence */
 272        {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */
 273        {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */
 274        /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */
 275#endif
 276
 277        {} /* terminator */
 278};
 279
 280/* SPDIF setup */
 281static void init_digital_coef(struct hda_codec *codec)
 282{
 283        unsigned int coef;
 284
 285        coef = 0x0002; /* SRC_MUTE soft-mute on SPDIF (if no lock) */
 286        coef |= 0x0008; /* Replace with mute on error */
 287        if (is_active_pin(codec, CS_DIG_OUT2_PIN_NID))
 288                coef |= 0x4000; /* RX to TX1 or TX2 Loopthru / SPDIF2
 289                                 * SPDIF_OUT2 is shared with GPIO1 and
 290                                 * DMIC_SDA2.
 291                                 */
 292        cs_vendor_coef_set(codec, IDX_SPDIF_CTL, coef);
 293}
 294
 295static int cs_init(struct hda_codec *codec)
 296{
 297        struct cs_spec *spec = codec->spec;
 298
 299        if (spec->vendor_nid == CS420X_VENDOR_NID) {
 300                /* init_verb sequence for C0/C1/C2 errata*/
 301                snd_hda_sequence_write(codec, cs_errata_init_verbs);
 302                snd_hda_sequence_write(codec, cs_coef_init_verbs);
 303        } else if (spec->vendor_nid == CS4208_VENDOR_NID) {
 304                snd_hda_sequence_write(codec, cs4208_coef_init_verbs);
 305        }
 306
 307        snd_hda_gen_init(codec);
 308
 309        if (spec->gpio_mask) {
 310                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
 311                                    spec->gpio_mask);
 312                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
 313                                    spec->gpio_dir);
 314                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
 315                                    spec->gpio_data);
 316        }
 317
 318        if (spec->vendor_nid == CS420X_VENDOR_NID) {
 319                init_input_coef(codec);
 320                init_digital_coef(codec);
 321        }
 322
 323        return 0;
 324}
 325
 326static int cs_build_controls(struct hda_codec *codec)
 327{
 328        int err;
 329
 330        err = snd_hda_gen_build_controls(codec);
 331        if (err < 0)
 332                return err;
 333        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
 334        return 0;
 335}
 336
 337#define cs_free         snd_hda_gen_free
 338
 339static const struct hda_codec_ops cs_patch_ops = {
 340        .build_controls = cs_build_controls,
 341        .build_pcms = snd_hda_gen_build_pcms,
 342        .init = cs_init,
 343        .free = cs_free,
 344        .unsol_event = snd_hda_jack_unsol_event,
 345};
 346
 347static int cs_parse_auto_config(struct hda_codec *codec)
 348{
 349        struct cs_spec *spec = codec->spec;
 350        int err;
 351        int i;
 352
 353        err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
 354        if (err < 0)
 355                return err;
 356
 357        err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
 358        if (err < 0)
 359                return err;
 360
 361        /* keep the ADCs powered up when it's dynamically switchable */
 362        if (spec->gen.dyn_adc_switch) {
 363                unsigned int done = 0;
 364                for (i = 0; i < spec->gen.input_mux.num_items; i++) {
 365                        int idx = spec->gen.dyn_adc_idx[i];
 366                        if (done & (1 << idx))
 367                                continue;
 368                        snd_hda_gen_fix_pin_power(codec,
 369                                                  spec->gen.adc_nids[idx]);
 370                        done |= 1 << idx;
 371                }
 372        }
 373
 374        return 0;
 375}
 376
 377static const struct hda_model_fixup cs420x_models[] = {
 378        { .id = CS420X_MBP53, .name = "mbp53" },
 379        { .id = CS420X_MBP55, .name = "mbp55" },
 380        { .id = CS420X_IMAC27, .name = "imac27" },
 381        { .id = CS420X_IMAC27_122, .name = "imac27_122" },
 382        { .id = CS420X_APPLE, .name = "apple" },
 383        { .id = CS420X_MBP101, .name = "mbp101" },
 384        { .id = CS420X_MBP81, .name = "mbp81" },
 385        { .id = CS420X_MBA42, .name = "mba42" },
 386        {}
 387};
 388
 389static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
 390        SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
 391        SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
 392        SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
 393        SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
 394        /* this conflicts with too many other models */
 395        /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/
 396
 397        /* codec SSID */
 398        SND_PCI_QUIRK(0x106b, 0x0600, "iMac 14,1", CS420X_IMAC27_122),
 399        SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81),
 400        SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
 401        SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101),
 402        SND_PCI_QUIRK(0x106b, 0x5600, "MacBookAir 5,2", CS420X_MBP81),
 403        SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42),
 404        SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
 405        {} /* terminator */
 406};
 407
 408static const struct hda_pintbl mbp53_pincfgs[] = {
 409        { 0x09, 0x012b4050 },
 410        { 0x0a, 0x90100141 },
 411        { 0x0b, 0x90100140 },
 412        { 0x0c, 0x018b3020 },
 413        { 0x0d, 0x90a00110 },
 414        { 0x0e, 0x400000f0 },
 415        { 0x0f, 0x01cbe030 },
 416        { 0x10, 0x014be060 },
 417        { 0x12, 0x400000f0 },
 418        { 0x15, 0x400000f0 },
 419        {} /* terminator */
 420};
 421
 422static const struct hda_pintbl mbp55_pincfgs[] = {
 423        { 0x09, 0x012b4030 },
 424        { 0x0a, 0x90100121 },
 425        { 0x0b, 0x90100120 },
 426        { 0x0c, 0x400000f0 },
 427        { 0x0d, 0x90a00110 },
 428        { 0x0e, 0x400000f0 },
 429        { 0x0f, 0x400000f0 },
 430        { 0x10, 0x014be040 },
 431        { 0x12, 0x400000f0 },
 432        { 0x15, 0x400000f0 },
 433        {} /* terminator */
 434};
 435
 436static const struct hda_pintbl imac27_pincfgs[] = {
 437        { 0x09, 0x012b4050 },
 438        { 0x0a, 0x90100140 },
 439        { 0x0b, 0x90100142 },
 440        { 0x0c, 0x018b3020 },
 441        { 0x0d, 0x90a00110 },
 442        { 0x0e, 0x400000f0 },
 443        { 0x0f, 0x01cbe030 },
 444        { 0x10, 0x014be060 },
 445        { 0x12, 0x01ab9070 },
 446        { 0x15, 0x400000f0 },
 447        {} /* terminator */
 448};
 449
 450static const struct hda_pintbl mbp101_pincfgs[] = {
 451        { 0x0d, 0x40ab90f0 },
 452        { 0x0e, 0x90a600f0 },
 453        { 0x12, 0x50a600f0 },
 454        {} /* terminator */
 455};
 456
 457static const struct hda_pintbl mba42_pincfgs[] = {
 458        { 0x09, 0x012b4030 }, /* HP */
 459        { 0x0a, 0x400000f0 },
 460        { 0x0b, 0x90100120 }, /* speaker */
 461        { 0x0c, 0x400000f0 },
 462        { 0x0d, 0x90a00110 }, /* mic */
 463        { 0x0e, 0x400000f0 },
 464        { 0x0f, 0x400000f0 },
 465        { 0x10, 0x400000f0 },
 466        { 0x12, 0x400000f0 },
 467        { 0x15, 0x400000f0 },
 468        {} /* terminator */
 469};
 470
 471static const struct hda_pintbl mba6_pincfgs[] = {
 472        { 0x10, 0x032120f0 }, /* HP */
 473        { 0x11, 0x500000f0 },
 474        { 0x12, 0x90100010 }, /* Speaker */
 475        { 0x13, 0x500000f0 },
 476        { 0x14, 0x500000f0 },
 477        { 0x15, 0x770000f0 },
 478        { 0x16, 0x770000f0 },
 479        { 0x17, 0x430000f0 },
 480        { 0x18, 0x43ab9030 }, /* Mic */
 481        { 0x19, 0x770000f0 },
 482        { 0x1a, 0x770000f0 },
 483        { 0x1b, 0x770000f0 },
 484        { 0x1c, 0x90a00090 },
 485        { 0x1d, 0x500000f0 },
 486        { 0x1e, 0x500000f0 },
 487        { 0x1f, 0x500000f0 },
 488        { 0x20, 0x500000f0 },
 489        { 0x21, 0x430000f0 },
 490        { 0x22, 0x430000f0 },
 491        {} /* terminator */
 492};
 493
 494static void cs420x_fixup_gpio_13(struct hda_codec *codec,
 495                                 const struct hda_fixup *fix, int action)
 496{
 497        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 498                struct cs_spec *spec = codec->spec;
 499                spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */
 500                spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
 501                spec->gpio_mask = spec->gpio_dir =
 502                        spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
 503        }
 504}
 505
 506static void cs420x_fixup_gpio_23(struct hda_codec *codec,
 507                                 const struct hda_fixup *fix, int action)
 508{
 509        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 510                struct cs_spec *spec = codec->spec;
 511                spec->gpio_eapd_hp = 4; /* GPIO2 = headphones */
 512                spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
 513                spec->gpio_mask = spec->gpio_dir =
 514                        spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
 515        }
 516}
 517
 518static const struct hda_fixup cs420x_fixups[] = {
 519        [CS420X_MBP53] = {
 520                .type = HDA_FIXUP_PINS,
 521                .v.pins = mbp53_pincfgs,
 522                .chained = true,
 523                .chain_id = CS420X_APPLE,
 524        },
 525        [CS420X_MBP55] = {
 526                .type = HDA_FIXUP_PINS,
 527                .v.pins = mbp55_pincfgs,
 528                .chained = true,
 529                .chain_id = CS420X_GPIO_13,
 530        },
 531        [CS420X_IMAC27] = {
 532                .type = HDA_FIXUP_PINS,
 533                .v.pins = imac27_pincfgs,
 534                .chained = true,
 535                .chain_id = CS420X_GPIO_13,
 536        },
 537        [CS420X_GPIO_13] = {
 538                .type = HDA_FIXUP_FUNC,
 539                .v.func = cs420x_fixup_gpio_13,
 540        },
 541        [CS420X_GPIO_23] = {
 542                .type = HDA_FIXUP_FUNC,
 543                .v.func = cs420x_fixup_gpio_23,
 544        },
 545        [CS420X_MBP101] = {
 546                .type = HDA_FIXUP_PINS,
 547                .v.pins = mbp101_pincfgs,
 548                .chained = true,
 549                .chain_id = CS420X_GPIO_13,
 550        },
 551        [CS420X_MBP81] = {
 552                .type = HDA_FIXUP_VERBS,
 553                .v.verbs = (const struct hda_verb[]) {
 554                        /* internal mic ADC2: right only, single ended */
 555                        {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG},
 556                        {0x11, AC_VERB_SET_PROC_COEF, 0x102a},
 557                        {}
 558                },
 559                .chained = true,
 560                .chain_id = CS420X_GPIO_13,
 561        },
 562        [CS420X_MBA42] = {
 563                .type = HDA_FIXUP_PINS,
 564                .v.pins = mba42_pincfgs,
 565                .chained = true,
 566                .chain_id = CS420X_GPIO_13,
 567        },
 568};
 569
 570static struct cs_spec *cs_alloc_spec(struct hda_codec *codec, int vendor_nid)
 571{
 572        struct cs_spec *spec;
 573
 574        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 575        if (!spec)
 576                return NULL;
 577        codec->spec = spec;
 578        spec->vendor_nid = vendor_nid;
 579        codec->power_save_node = 1;
 580        snd_hda_gen_spec_init(&spec->gen);
 581
 582        return spec;
 583}
 584
 585static int patch_cs420x(struct hda_codec *codec)
 586{
 587        struct cs_spec *spec;
 588        int err;
 589
 590        spec = cs_alloc_spec(codec, CS420X_VENDOR_NID);
 591        if (!spec)
 592                return -ENOMEM;
 593
 594        codec->patch_ops = cs_patch_ops;
 595        spec->gen.automute_hook = cs_automute;
 596        codec->single_adc_amp = 1;
 597
 598        snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl,
 599                           cs420x_fixups);
 600        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 601
 602        err = cs_parse_auto_config(codec);
 603        if (err < 0)
 604                goto error;
 605
 606        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 607
 608        return 0;
 609
 610 error:
 611        cs_free(codec);
 612        return err;
 613}
 614
 615/*
 616 * CS4208 support:
 617 * Its layout is no longer compatible with CS4206/CS4207
 618 */
 619enum {
 620        CS4208_MAC_AUTO,
 621        CS4208_MBA6,
 622        CS4208_MBP11,
 623        CS4208_MACMINI,
 624        CS4208_GPIO0,
 625};
 626
 627static const struct hda_model_fixup cs4208_models[] = {
 628        { .id = CS4208_GPIO0, .name = "gpio0" },
 629        { .id = CS4208_MBA6, .name = "mba6" },
 630        { .id = CS4208_MBP11, .name = "mbp11" },
 631        { .id = CS4208_MACMINI, .name = "macmini" },
 632        {}
 633};
 634
 635static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
 636        SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS4208_MAC_AUTO),
 637        {} /* terminator */
 638};
 639
 640/* codec SSID matching */
 641static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
 642        SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
 643        SND_PCI_QUIRK(0x106b, 0x6c00, "MacMini 7,1", CS4208_MACMINI),
 644        SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
 645        SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
 646        SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
 647        {} /* terminator */
 648};
 649
 650static void cs4208_fixup_gpio0(struct hda_codec *codec,
 651                               const struct hda_fixup *fix, int action)
 652{
 653        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 654                struct cs_spec *spec = codec->spec;
 655                spec->gpio_eapd_hp = 0;
 656                spec->gpio_eapd_speaker = 1;
 657                spec->gpio_mask = spec->gpio_dir =
 658                        spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
 659        }
 660}
 661
 662static const struct hda_fixup cs4208_fixups[];
 663
 664/* remap the fixup from codec SSID and apply it */
 665static void cs4208_fixup_mac(struct hda_codec *codec,
 666                             const struct hda_fixup *fix, int action)
 667{
 668        if (action != HDA_FIXUP_ACT_PRE_PROBE)
 669                return;
 670
 671        codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
 672        snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups);
 673        if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET)
 674                codec->fixup_id = CS4208_GPIO0; /* default fixup */
 675        snd_hda_apply_fixup(codec, action);
 676}
 677
 678/* MacMini 7,1 has the inverted jack detection */
 679static void cs4208_fixup_macmini(struct hda_codec *codec,
 680                                 const struct hda_fixup *fix, int action)
 681{
 682        static const struct hda_pintbl pincfgs[] = {
 683                { 0x18, 0x00ab9150 }, /* mic (audio-in) jack: disable detect */
 684                { 0x21, 0x004be140 }, /* SPDIF: disable detect */
 685                { }
 686        };
 687
 688        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 689                /* HP pin (0x10) has an inverted detection */
 690                codec->inv_jack_detect = 1;
 691                /* disable the bogus Mic and SPDIF jack detections */
 692                snd_hda_apply_pincfgs(codec, pincfgs);
 693        }
 694}
 695
 696static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol,
 697                               struct snd_ctl_elem_value *ucontrol)
 698{
 699        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 700        struct cs_spec *spec = codec->spec;
 701        hda_nid_t pin = spec->gen.autocfg.dig_out_pins[0];
 702        int pinctl = ucontrol->value.integer.value[0] ? PIN_OUT : 0;
 703
 704        snd_hda_set_pin_ctl_cache(codec, pin, pinctl);
 705        return spec->spdif_sw_put(kcontrol, ucontrol);
 706}
 707
 708/* hook the SPDIF switch */
 709static void cs4208_fixup_spdif_switch(struct hda_codec *codec,
 710                                      const struct hda_fixup *fix, int action)
 711{
 712        if (action == HDA_FIXUP_ACT_BUILD) {
 713                struct cs_spec *spec = codec->spec;
 714                struct snd_kcontrol *kctl;
 715
 716                if (!spec->gen.autocfg.dig_out_pins[0])
 717                        return;
 718                kctl = snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch");
 719                if (!kctl)
 720                        return;
 721                spec->spdif_sw_put = kctl->put;
 722                kctl->put = cs4208_spdif_sw_put;
 723        }
 724}
 725
 726static const struct hda_fixup cs4208_fixups[] = {
 727        [CS4208_MBA6] = {
 728                .type = HDA_FIXUP_PINS,
 729                .v.pins = mba6_pincfgs,
 730                .chained = true,
 731                .chain_id = CS4208_GPIO0,
 732        },
 733        [CS4208_MBP11] = {
 734                .type = HDA_FIXUP_FUNC,
 735                .v.func = cs4208_fixup_spdif_switch,
 736                .chained = true,
 737                .chain_id = CS4208_GPIO0,
 738        },
 739        [CS4208_MACMINI] = {
 740                .type = HDA_FIXUP_FUNC,
 741                .v.func = cs4208_fixup_macmini,
 742                .chained = true,
 743                .chain_id = CS4208_GPIO0,
 744        },
 745        [CS4208_GPIO0] = {
 746                .type = HDA_FIXUP_FUNC,
 747                .v.func = cs4208_fixup_gpio0,
 748        },
 749        [CS4208_MAC_AUTO] = {
 750                .type = HDA_FIXUP_FUNC,
 751                .v.func = cs4208_fixup_mac,
 752        },
 753};
 754
 755/* correct the 0dB offset of input pins */
 756static void cs4208_fix_amp_caps(struct hda_codec *codec, hda_nid_t adc)
 757{
 758        unsigned int caps;
 759
 760        caps = query_amp_caps(codec, adc, HDA_INPUT);
 761        caps &= ~(AC_AMPCAP_OFFSET);
 762        caps |= 0x02;
 763        snd_hda_override_amp_caps(codec, adc, HDA_INPUT, caps);
 764}
 765
 766static int patch_cs4208(struct hda_codec *codec)
 767{
 768        struct cs_spec *spec;
 769        int err;
 770
 771        spec = cs_alloc_spec(codec, CS4208_VENDOR_NID);
 772        if (!spec)
 773                return -ENOMEM;
 774
 775        codec->patch_ops = cs_patch_ops;
 776        spec->gen.automute_hook = cs_automute;
 777        /* exclude NID 0x10 (HP) from output volumes due to different steps */
 778        spec->gen.out_vol_mask = 1ULL << 0x10;
 779
 780        snd_hda_pick_fixup(codec, cs4208_models, cs4208_fixup_tbl,
 781                           cs4208_fixups);
 782        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 783
 784        snd_hda_override_wcaps(codec, 0x18,
 785                               get_wcaps(codec, 0x18) | AC_WCAP_STEREO);
 786        cs4208_fix_amp_caps(codec, 0x18);
 787        cs4208_fix_amp_caps(codec, 0x1b);
 788        cs4208_fix_amp_caps(codec, 0x1c);
 789
 790        err = cs_parse_auto_config(codec);
 791        if (err < 0)
 792                goto error;
 793
 794        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 795
 796        return 0;
 797
 798 error:
 799        cs_free(codec);
 800        return err;
 801}
 802
 803/*
 804 * Cirrus Logic CS4210
 805 *
 806 * 1 DAC => HP(sense) / Speakers,
 807 * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
 808 * 1 SPDIF OUT => SPDIF Trasmitter(sense)
 809*/
 810
 811/* CS4210 board names */
 812static const struct hda_model_fixup cs421x_models[] = {
 813        { .id = CS421X_CDB4210, .name = "cdb4210" },
 814        { .id = CS421X_STUMPY, .name = "stumpy" },
 815        {}
 816};
 817
 818static const struct snd_pci_quirk cs421x_fixup_tbl[] = {
 819        /* Test Intel board + CDB2410  */
 820        SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210),
 821        {} /* terminator */
 822};
 823
 824/* CS4210 board pinconfigs */
 825/* Default CS4210 (CDB4210)*/
 826static const struct hda_pintbl cdb4210_pincfgs[] = {
 827        { 0x05, 0x0321401f },
 828        { 0x06, 0x90170010 },
 829        { 0x07, 0x03813031 },
 830        { 0x08, 0xb7a70037 },
 831        { 0x09, 0xb7a6003e },
 832        { 0x0a, 0x034510f0 },
 833        {} /* terminator */
 834};
 835
 836/* Stumpy ChromeBox */
 837static const struct hda_pintbl stumpy_pincfgs[] = {
 838        { 0x05, 0x022120f0 },
 839        { 0x06, 0x901700f0 },
 840        { 0x07, 0x02a120f0 },
 841        { 0x08, 0x77a70037 },
 842        { 0x09, 0x77a6003e },
 843        { 0x0a, 0x434510f0 },
 844        {} /* terminator */
 845};
 846
 847/* Setup GPIO/SENSE for each board (if used) */
 848static void cs421x_fixup_sense_b(struct hda_codec *codec,
 849                                 const struct hda_fixup *fix, int action)
 850{
 851        struct cs_spec *spec = codec->spec;
 852        if (action == HDA_FIXUP_ACT_PRE_PROBE)
 853                spec->sense_b = 1;
 854}
 855
 856static const struct hda_fixup cs421x_fixups[] = {
 857        [CS421X_CDB4210] = {
 858                .type = HDA_FIXUP_PINS,
 859                .v.pins = cdb4210_pincfgs,
 860                .chained = true,
 861                .chain_id = CS421X_SENSE_B,
 862        },
 863        [CS421X_SENSE_B] = {
 864                .type = HDA_FIXUP_FUNC,
 865                .v.func = cs421x_fixup_sense_b,
 866        },
 867        [CS421X_STUMPY] = {
 868                .type = HDA_FIXUP_PINS,
 869                .v.pins = stumpy_pincfgs,
 870        },
 871};
 872
 873static const struct hda_verb cs421x_coef_init_verbs[] = {
 874        {0x0B, AC_VERB_SET_PROC_STATE, 1},
 875        {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DEV_CFG},
 876        /*
 877            Disable Coefficient Index Auto-Increment(DAI)=1,
 878            PDREF=0
 879        */
 880        {0x0B, AC_VERB_SET_PROC_COEF, 0x0001 },
 881
 882        {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_ADC_CFG},
 883        /* ADC SZCMode = Digital Soft Ramp */
 884        {0x0B, AC_VERB_SET_PROC_COEF, 0x0002 },
 885
 886        {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DAC_CFG},
 887        {0x0B, AC_VERB_SET_PROC_COEF,
 888         (0x0002 /* DAC SZCMode = Digital Soft Ramp */
 889          | 0x0004 /* Mute DAC on FIFO error */
 890          | 0x0008 /* Enable DAC High Pass Filter */
 891          )},
 892        {} /* terminator */
 893};
 894
 895/* Errata: CS4210 rev A1 Silicon
 896 *
 897 * http://www.cirrus.com/en/pubs/errata/
 898 *
 899 * Description:
 900 * 1. Performance degredation is present in the ADC.
 901 * 2. Speaker output is not completely muted upon HP detect.
 902 * 3. Noise is present when clipping occurs on the amplified
 903 *    speaker outputs.
 904 *
 905 * Workaround:
 906 * The following verb sequence written to the registers during
 907 * initialization will correct the issues listed above.
 908 */
 909
 910static const struct hda_verb cs421x_coef_init_verbs_A1_silicon_fixes[] = {
 911        {0x0B, AC_VERB_SET_PROC_STATE, 0x01},  /* VPW: processing on */
 912
 913        {0x0B, AC_VERB_SET_COEF_INDEX, 0x0006},
 914        {0x0B, AC_VERB_SET_PROC_COEF, 0x9999}, /* Test mode: on */
 915
 916        {0x0B, AC_VERB_SET_COEF_INDEX, 0x000A},
 917        {0x0B, AC_VERB_SET_PROC_COEF, 0x14CB}, /* Chop double */
 918
 919        {0x0B, AC_VERB_SET_COEF_INDEX, 0x0011},
 920        {0x0B, AC_VERB_SET_PROC_COEF, 0xA2D0}, /* Increase ADC current */
 921
 922        {0x0B, AC_VERB_SET_COEF_INDEX, 0x001A},
 923        {0x0B, AC_VERB_SET_PROC_COEF, 0x02A9}, /* Mute speaker */
 924
 925        {0x0B, AC_VERB_SET_COEF_INDEX, 0x001B},
 926        {0x0B, AC_VERB_SET_PROC_COEF, 0X1006}, /* Remove noise */
 927
 928        {} /* terminator */
 929};
 930
 931/* Speaker Amp Gain is controlled by the vendor widget's coef 4 */
 932static const DECLARE_TLV_DB_SCALE(cs421x_speaker_boost_db_scale, 900, 300, 0);
 933
 934static int cs421x_boost_vol_info(struct snd_kcontrol *kcontrol,
 935                                struct snd_ctl_elem_info *uinfo)
 936{
 937        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 938        uinfo->count = 1;
 939        uinfo->value.integer.min = 0;
 940        uinfo->value.integer.max = 3;
 941        return 0;
 942}
 943
 944static int cs421x_boost_vol_get(struct snd_kcontrol *kcontrol,
 945                                struct snd_ctl_elem_value *ucontrol)
 946{
 947        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 948
 949        ucontrol->value.integer.value[0] =
 950                cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL) & 0x0003;
 951        return 0;
 952}
 953
 954static int cs421x_boost_vol_put(struct snd_kcontrol *kcontrol,
 955                                struct snd_ctl_elem_value *ucontrol)
 956{
 957        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 958
 959        unsigned int vol = ucontrol->value.integer.value[0];
 960        unsigned int coef =
 961                cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL);
 962        unsigned int original_coef = coef;
 963
 964        coef &= ~0x0003;
 965        coef |= (vol & 0x0003);
 966        if (original_coef == coef)
 967                return 0;
 968        else {
 969                cs_vendor_coef_set(codec, CS421X_IDX_SPK_CTL, coef);
 970                return 1;
 971        }
 972}
 973
 974static const struct snd_kcontrol_new cs421x_speaker_boost_ctl = {
 975
 976        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 977        .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 978                        SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 979        .name = "Speaker Boost Playback Volume",
 980        .info = cs421x_boost_vol_info,
 981        .get = cs421x_boost_vol_get,
 982        .put = cs421x_boost_vol_put,
 983        .tlv = { .p = cs421x_speaker_boost_db_scale },
 984};
 985
 986static void cs4210_pinmux_init(struct hda_codec *codec)
 987{
 988        struct cs_spec *spec = codec->spec;
 989        unsigned int def_conf, coef;
 990
 991        /* GPIO, DMIC_SCL, DMIC_SDA and SENSE_B are multiplexed */
 992        coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
 993
 994        if (spec->gpio_mask)
 995                coef |= 0x0008; /* B1,B2 are GPIOs */
 996        else
 997                coef &= ~0x0008;
 998
 999        if (spec->sense_b)
1000                coef |= 0x0010; /* B2 is SENSE_B, not inverted  */
1001        else
1002                coef &= ~0x0010;
1003
1004        cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
1005
1006        if ((spec->gpio_mask || spec->sense_b) &&
1007            is_active_pin(codec, CS421X_DMIC_PIN_NID)) {
1008
1009                /*
1010                    GPIO or SENSE_B forced - disconnect the DMIC pin.
1011                */
1012                def_conf = snd_hda_codec_get_pincfg(codec, CS421X_DMIC_PIN_NID);
1013                def_conf &= ~AC_DEFCFG_PORT_CONN;
1014                def_conf |= (AC_JACK_PORT_NONE << AC_DEFCFG_PORT_CONN_SHIFT);
1015                snd_hda_codec_set_pincfg(codec, CS421X_DMIC_PIN_NID, def_conf);
1016        }
1017}
1018
1019static void cs4210_spdif_automute(struct hda_codec *codec,
1020                                  struct hda_jack_callback *tbl)
1021{
1022        struct cs_spec *spec = codec->spec;
1023        bool spdif_present = false;
1024        hda_nid_t spdif_pin = spec->gen.autocfg.dig_out_pins[0];
1025
1026        /* detect on spdif is specific to CS4210 */
1027        if (!spec->spdif_detect ||
1028            spec->vendor_nid != CS4210_VENDOR_NID)
1029                return;
1030
1031        spdif_present = snd_hda_jack_detect(codec, spdif_pin);
1032        if (spdif_present == spec->spdif_present)
1033                return;
1034
1035        spec->spdif_present = spdif_present;
1036        /* SPDIF TX on/off */
1037        snd_hda_set_pin_ctl(codec, spdif_pin, spdif_present ? PIN_OUT : 0);
1038
1039        cs_automute(codec);
1040}
1041
1042static void parse_cs421x_digital(struct hda_codec *codec)
1043{
1044        struct cs_spec *spec = codec->spec;
1045        struct auto_pin_cfg *cfg = &spec->gen.autocfg;
1046        int i;
1047
1048        for (i = 0; i < cfg->dig_outs; i++) {
1049                hda_nid_t nid = cfg->dig_out_pins[i];
1050                if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
1051                        spec->spdif_detect = 1;
1052                        snd_hda_jack_detect_enable_callback(codec, nid,
1053                                                            cs4210_spdif_automute);
1054                }
1055        }
1056}
1057
1058static int cs421x_init(struct hda_codec *codec)
1059{
1060        struct cs_spec *spec = codec->spec;
1061
1062        if (spec->vendor_nid == CS4210_VENDOR_NID) {
1063                snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
1064                snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
1065                cs4210_pinmux_init(codec);
1066        }
1067
1068        snd_hda_gen_init(codec);
1069
1070        if (spec->gpio_mask) {
1071                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
1072                                    spec->gpio_mask);
1073                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
1074                                    spec->gpio_dir);
1075                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
1076                                    spec->gpio_data);
1077        }
1078
1079        init_input_coef(codec);
1080
1081        cs4210_spdif_automute(codec, NULL);
1082
1083        return 0;
1084}
1085
1086static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac)
1087{
1088        unsigned int caps;
1089
1090        /* set the upper-limit for mixer amp to 0dB */
1091        caps = query_amp_caps(codec, dac, HDA_OUTPUT);
1092        caps &= ~(0x7f << AC_AMPCAP_NUM_STEPS_SHIFT);
1093        caps |= ((caps >> AC_AMPCAP_OFFSET_SHIFT) & 0x7f)
1094                << AC_AMPCAP_NUM_STEPS_SHIFT;
1095        snd_hda_override_amp_caps(codec, dac, HDA_OUTPUT, caps);
1096}
1097
1098static int cs421x_parse_auto_config(struct hda_codec *codec)
1099{
1100        struct cs_spec *spec = codec->spec;
1101        hda_nid_t dac = CS4210_DAC_NID;
1102        int err;
1103
1104        fix_volume_caps(codec, dac);
1105
1106        err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
1107        if (err < 0)
1108                return err;
1109
1110        err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
1111        if (err < 0)
1112                return err;
1113
1114        parse_cs421x_digital(codec);
1115
1116        if (spec->gen.autocfg.speaker_outs &&
1117            spec->vendor_nid == CS4210_VENDOR_NID) {
1118                if (!snd_hda_gen_add_kctl(&spec->gen, NULL,
1119                                          &cs421x_speaker_boost_ctl))
1120                        return -ENOMEM;
1121        }
1122
1123        return 0;
1124}
1125
1126#ifdef CONFIG_PM
1127/*
1128        Manage PDREF, when transitioning to D3hot
1129        (DAC,ADC) -> D3, PDREF=1, AFG->D3
1130*/
1131static int cs421x_suspend(struct hda_codec *codec)
1132{
1133        struct cs_spec *spec = codec->spec;
1134        unsigned int coef;
1135
1136        snd_hda_shutup_pins(codec);
1137
1138        snd_hda_codec_write(codec, CS4210_DAC_NID, 0,
1139                            AC_VERB_SET_POWER_STATE,  AC_PWRST_D3);
1140        snd_hda_codec_write(codec, CS4210_ADC_NID, 0,
1141                            AC_VERB_SET_POWER_STATE,  AC_PWRST_D3);
1142
1143        if (spec->vendor_nid == CS4210_VENDOR_NID) {
1144                coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
1145                coef |= 0x0004; /* PDREF */
1146                cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
1147        }
1148
1149        return 0;
1150}
1151#endif
1152
1153static const struct hda_codec_ops cs421x_patch_ops = {
1154        .build_controls = snd_hda_gen_build_controls,
1155        .build_pcms = snd_hda_gen_build_pcms,
1156        .init = cs421x_init,
1157        .free = cs_free,
1158        .unsol_event = snd_hda_jack_unsol_event,
1159#ifdef CONFIG_PM
1160        .suspend = cs421x_suspend,
1161#endif
1162};
1163
1164static int patch_cs4210(struct hda_codec *codec)
1165{
1166        struct cs_spec *spec;
1167        int err;
1168
1169        spec = cs_alloc_spec(codec, CS4210_VENDOR_NID);
1170        if (!spec)
1171                return -ENOMEM;
1172
1173        codec->patch_ops = cs421x_patch_ops;
1174        spec->gen.automute_hook = cs_automute;
1175
1176        snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl,
1177                           cs421x_fixups);
1178        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1179
1180        /*
1181            Update the GPIO/DMIC/SENSE_B pinmux before the configuration
1182            is auto-parsed. If GPIO or SENSE_B is forced, DMIC input
1183            is disabled.
1184        */
1185        cs4210_pinmux_init(codec);
1186
1187        err = cs421x_parse_auto_config(codec);
1188        if (err < 0)
1189                goto error;
1190
1191        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
1192
1193        return 0;
1194
1195 error:
1196        cs_free(codec);
1197        return err;
1198}
1199
1200static int patch_cs4213(struct hda_codec *codec)
1201{
1202        struct cs_spec *spec;
1203        int err;
1204
1205        spec = cs_alloc_spec(codec, CS4213_VENDOR_NID);
1206        if (!spec)
1207                return -ENOMEM;
1208
1209        codec->patch_ops = cs421x_patch_ops;
1210
1211        err = cs421x_parse_auto_config(codec);
1212        if (err < 0)
1213                goto error;
1214
1215        return 0;
1216
1217 error:
1218        cs_free(codec);
1219        return err;
1220}
1221
1222
1223/*
1224 * patch entries
1225 */
1226static const struct hda_device_id snd_hda_id_cirrus[] = {
1227        HDA_CODEC_ENTRY(0x10134206, "CS4206", patch_cs420x),
1228        HDA_CODEC_ENTRY(0x10134207, "CS4207", patch_cs420x),
1229        HDA_CODEC_ENTRY(0x10134208, "CS4208", patch_cs4208),
1230        HDA_CODEC_ENTRY(0x10134210, "CS4210", patch_cs4210),
1231        HDA_CODEC_ENTRY(0x10134213, "CS4213", patch_cs4213),
1232        {} /* terminator */
1233};
1234MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cirrus);
1235
1236MODULE_LICENSE("GPL");
1237MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");
1238
1239static struct hda_codec_driver cirrus_driver = {
1240        .id = snd_hda_id_cirrus,
1241};
1242
1243module_hda_codec_driver(cirrus_driver);
1244