root/sound/pci/hda/patch_cirrus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cs_vendor_coef_get
  2. cs_vendor_coef_set
  3. cs_automute
  4. is_active_pin
  5. init_input_coef
  6. init_digital_coef
  7. cs_init
  8. cs_build_controls
  9. cs_parse_auto_config
  10. cs420x_fixup_gpio_13
  11. cs420x_fixup_gpio_23
  12. cs_alloc_spec
  13. patch_cs420x
  14. cs4208_fixup_gpio0
  15. cs4208_fixup_mac
  16. cs4208_fixup_macmini
  17. cs4208_spdif_sw_put
  18. cs4208_fixup_spdif_switch
  19. cs4208_fix_amp_caps
  20. patch_cs4208
  21. cs421x_fixup_sense_b
  22. cs421x_boost_vol_info
  23. cs421x_boost_vol_get
  24. cs421x_boost_vol_put
  25. cs4210_pinmux_init
  26. cs4210_spdif_automute
  27. parse_cs421x_digital
  28. cs421x_init
  29. fix_volume_caps
  30. cs421x_parse_auto_config
  31. cs421x_suspend
  32. patch_cs4210
  33. patch_cs4213

   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 
  22 struct 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 */
  43 enum {
  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 */
  59 enum {
  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 
 129 static 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 
 138 static 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 
 154 static 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 
 175 static 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 
 182 static 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 
 202 static 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 
 221 static 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 
 249 static 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 */
 281 static 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 
 295 static 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 
 326 static 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 
 339 static 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 
 347 static 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 
 377 static 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 
 389 static 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 
 408 static 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 
 422 static 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 
 436 static 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 
 450 static const struct hda_pintbl mbp101_pincfgs[] = {
 451         { 0x0d, 0x40ab90f0 },
 452         { 0x0e, 0x90a600f0 },
 453         { 0x12, 0x50a600f0 },
 454         {} /* terminator */
 455 };
 456 
 457 static 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 
 471 static 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 
 494 static 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 
 506 static 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 
 518 static 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 
 570 static 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 
 585 static 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  */
 619 enum {
 620         CS4208_MAC_AUTO,
 621         CS4208_MBA6,
 622         CS4208_MBP11,
 623         CS4208_MACMINI,
 624         CS4208_GPIO0,
 625 };
 626 
 627 static 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 
 635 static 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 */
 641 static 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 
 650 static 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 
 662 static const struct hda_fixup cs4208_fixups[];
 663 
 664 /* remap the fixup from codec SSID and apply it */
 665 static 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 */
 679 static 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 
 696 static 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 */
 709 static 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 
 726 static 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 */
 756 static 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 
 766 static 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 */
 812 static const struct hda_model_fixup cs421x_models[] = {
 813         { .id = CS421X_CDB4210, .name = "cdb4210" },
 814         { .id = CS421X_STUMPY, .name = "stumpy" },
 815         {}
 816 };
 817 
 818 static 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)*/
 826 static 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 */
 837 static 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) */
 848 static 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 
 856 static 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 
 873 static 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 
 910 static 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 */
 932 static const DECLARE_TLV_DB_SCALE(cs421x_speaker_boost_db_scale, 900, 300, 0);
 933 
 934 static 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 
 944 static 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 
 954 static 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 
 974 static 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 
 986 static 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 
1019 static 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 
1042 static 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 
1058 static 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 
1086 static 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 
1098 static 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 */
1131 static 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 
1153 static 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 
1164 static 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 
1200 static 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  */
1226 static 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 };
1234 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cirrus);
1235 
1236 MODULE_LICENSE("GPL");
1237 MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");
1238 
1239 static struct hda_codec_driver cirrus_driver = {
1240         .id = snd_hda_id_cirrus,
1241 };
1242 
1243 module_hda_codec_driver(cirrus_driver);

/* [<][>][^][v][top][bottom][index][help] */